2024-06-03.md
π‘DIL: μ΄νν°λΈ νμ μ€ν¬λ¦½νΈ
μ€ν°λ: μκ° CS, https://github.com/monthly-cs/2024-05-effective-typescript
μμ±μΌ: 2024-06-03
μμ±μ: dusunax
5μ₯: any λ€λ£¨κΈ° Use the Narrowest Possible Scope for any Types
- νμ μμ€ν μ νμ (option) μ΄κ³ μ μ§μ (gradual) μ΄κΈ° λλ¬Έμ μ μ μ΄λ©΄μλ λμ μΈ νΉμ±μ κ°μ§ λμμ κ°μ§λ€.
μ νμ νμ μμ€ν (Optional Typing)
- νλ‘κ·Έλ¨μ μΌλΆμλ§ νμ
μμ€ν
μ μ μ©ν μ μλ€ -> μ μ§μ λ§μ΄κ·Έλ μ΄μ
- νμ 체ν¬λ₯Ό λΉνμ±νμμΌμ£Όλ any νμ
μ μ§μ νμ μμ€ν (Gradual Typing)
- μμ€ν μ΄ λΆλΆμ μΌλ‘ νμ μ κ²μ¦νλ λ°©μ. μ½λμ μΌλΆλ λμ μΌλ‘, λ€λ₯Έ μΌλΆλ μ μ μΌλ‘ νμ κ²μ¬λ₯Ό μνν μ μek.
- νμμ λ°λΌ μ μ§μ μΌλ‘ νμ μ μΆκ°ν μ μλ€. μ΄κΈ°μλ λμ νμ μΌλ‘ μμνκ³ , μ μ°¨ μ μ νμ μ μΆκ°νμ¬ νμ μμ μ±μ λμΌ μ μλ€.
λμ νΉμ± vs μ μ νΉμ±
- λμ νΉμ±
- λμ νμ΄ν: νμ μ λͺ μνμ§ μμ λ³μλ ν¨μλ λμ μΌλ‘ νμ μ΄ κ²°μ λλ€. μ¦, λ°νμ μμ λ³μμ νμ μ΄ κ²°μ λλ©°, λ€μν νμ μ κ°μ κ°μ§ μ μλ€.
- νμ μ λͺ μνμ§ μμ λΆλΆμ λ°νμμ λμ μΌλ‘ νμ μ κ²°μ
- λμ νμ μΈμ΄μ μ₯μ μΈ κ°κ²°ν λ¬Έλ²κ³Ό λΉ λ₯Έ κ°λ° μ¬μ΄ν΄μ μ μ§. μ μ°ν¨!
- μ μ νΉμ±
- μ μ νμ΄ν: νμ μ λͺ μν λ³μλ ν¨μλ μ μ μΌλ‘ νμ μ΄ κ²°μ λλ€. μ¦, μ»΄νμΌ μμ νμ μ΄ κ³ μ λλ©°, ν΄λΉ νμ μ κ°λ§μ κ°μ§ μ μλ€.
- μ»΄νμΌ νμμ νμ μ€λ₯λ₯Ό λ°κ²¬νκ³ μμ
- νμ μ λͺ μν¨μΌλ‘μ¨, IDEμμμ μλ μμ±, μ½λ 리ν©ν λ§, νμ μμ μ± λ±μ νν
μμ΄ν 38: any νμ μ κ°λ₯ν ν μ’μ λ²μμμλ§ μ¬μ©νκΈ° Use the Narrowest Possible Scope for any Types
ν¨μμ any
- 맀κ°λ³μμλ§ μ¬μ©νκΈ°
- ν¨μμ λ°ν νμ μ? anyκ° λ°νλμ΄ ν¨μ λ°κΉ₯μ μν₯μ λ―ΈμΉλ κ²μ λ°©μ§νκΈ° μν΄ λ°ν νμ μ λͺ μνλ κ²μ΄ μ’λ€.
function f1() {
const x: any = expressionReturningFoo(); // β π€§
processBar(x);
}
function f2() {
const x = expressionReturningFoo(); // better.
processBar(x as any);
// ν¨μμ 맀κ°λ³μμλ§ μ¬μ©λ ννμμ΄λ―λ‘ λ€λ₯Έ μ½λμλ μν₯μ λ―ΈμΉμ§ μκΈ° λλ¬Έ
// @ts-ignore, @ts-expect-errorλ₯Ό μ¬μ©ν΄μ anyλ₯Ό μ¬μ©νμ§ μκ³ μ€λ₯ μ κ±°λ κ°λ₯. (λ°νμ μ€λ₯ κ°λ₯μ±)
}
κ°μ²΄ μμ±κ³Ό any
const config: Config = {
a: 1,
b: 2,
c: {
key: value,
},
} as any; // β
const config: Config = {
a: 1,
b: 2, // λ€λ₯Έ μμ±μ νμ
체ν¬
c: {
key: value as any, // νμν μμ±μ κ°λ§ any
},
};
Things to Remember
- Make your uses of any as narrowly scoped as possible to avoid undesired loss of type safety elsewhere in your code.
- μλμΉ μμ νμ μμ μ±μ μμ€μ νΌνκΈ° μν΄μ, anyλ₯Ό μ΅λν μ’κ² μ¬μ©ν κ²
- Never return an any type from a function. This will silently lead to the loss of type safety for code that calls the function.
- λΉμ μ΄ anyλ₯Ό λ°ννλ€λ©΄... ν¨μλ₯Ό νΈμΆν κ³³μμ νμ μμ μ±μ μ무λ λͺ¨λ₯΄κ² μ‘°μ©ν μκ² λλ€....π
- Use as any on individual properties of a larger object instead of the whole object.
- μ 체 κ°μ²΄ anyλ₯Ό μ¬μ©νμ§ λ§κ³ , κ°λ³ μμ±μ μ μ©ν κ²
μμ΄ν 39: anyλ₯Ό ꡬ체μ μΌλ‘ λ³νν΄μ μ¬μ©νκΈ° Prefer More Precise Variants of any to Plain any
- anyλ? μλ°μ€ν¬λ¦½νΈμμ ννν μ μλ λͺ¨λ κ°μ λ²μ
- μ«μ, λ¬Έμμ΄, λ°°μ΄, κ°μ²΄, μ κ·μ, ν¨μ, ν΄λμ€, DOM μ리먼νΈ, null, undefined
- any보λ€λ λ ꡬ체μ μΌλ‘ ννν μ μλ νμ μ΄ μλ€!
μμ: any 보λ€λ any[]
- ν¨μ λ΄μ array.length νμ 체ν¬
- ν¨μμ λ°ν νμ μ΄ any λμ number
- ν¨μκ° νΈμΆλ λ, 맀κ°λ³μκ° λ°°μ΄μΈμ§ 체ν¬
function getLengthBad(array: any) {
// β
return array.length;
}
getLengthBad(/123/);
getLengthBad(null);
function getLength(array: any[]) {
return array.length; // This is better !
}
getLength(/123/); // μ€λ₯
// ~~~~~
// Argument of type 'RegExp' is not assignable to parameter of type 'any[]'.
getLength(null); // μ€λ₯
// ~~~~
// Argument of type 'null' is not assignable to parameter of type 'any[]'.
- μ΄μ€λ°°μ΄μ?
any[][]
- κ°μ μ μ μλ κ°μ²΄λ€?
{[key: string]: any}
&&Record<string, any>
- ꡬ체μ μΈ ν€μ κ°μ νμ μ λμ μΌλ‘ μ μ
object
- λΉκΈ°λ³Έν non-primitive νμ μ ν¬ν¨νλ object νμ , ν€λ₯Ό μ΄κ±°ν μ μμ§λ§, μμ±μ μ κ·Όν μ μλ€
- κ°μ²΄μ ꡬ쑰λ νλ‘νΌν°μ λν΄ νμ
κ²μ¬λ₯Ό ν μ μλ€.
- μλ? ꡬ체μ μΈ ν€-κ° μμ λνλ΄μ§ μκΈ° λλ¬Έ
- κ°μ²΄μ΄μ§λ§ μμ±μ μ κ·Όν μ μμ΄μΌ νλ€λ©΄? unknown => μ΄ν μμ΄ν 42μ λλ₯λ₯μ₯ μμ
function hasAKeyThatEndsWithZ(o: Record<string, any>) {
for (const key in o) {
if (key.endsWith("z")) {
console.log(key, o[key]); // keyλ₯Ό ν΅ν΄ μμ±μ μ κ·Ό
return true;
}
}
return false;
}
function hasAKeyThatEndsWithZ(o: object) {
for (const key in o) {
if (key.endsWith("z")) {
console.log(key, o[key]);
// ~~~~~~ Element implicitly has an 'any' type
// because type '{}' has no index signature
// {} νμμ μΈλ±μ€ μκ·Έλμ²κ° μμΌλ―λ‘ μμμ μμμ μΈ anyκ° μμ
return true;
}
}
return false;
}
ν¨μμ νμ κ³Ό any
type Fn0 = () => any; // 맀κ°λ³μ μμ΄ νΈμΆ κ°λ₯ν λͺ¨λ ν¨μ
type Fn1 = (arg: any) => any; // 맀κ°λ³μ 1κ°
type FnN = (...args: any[]) => any; // λͺ¨λ κ°μμ 맀κ°λ³μ === Function
// argsκ° λ°°μ΄ ννμμ μ μ μλ€.
const numArgsBad = (...args: any) => args.length; // anyλ₯Ό λ°ννλ€
const numArgsGood = (...args: any[]) => args.length; // nubmerλ₯Ό λ°ννλ€
Things to Remember
- When you use any, think about whether any JavaScript value is truly permissible.
- anyλ₯Ό μ¬μ©ν λ, λͺ¨λ μλ°μ€ν¬λ¦½νΈ κ°μ΄ μ λ§λ‘ νμ©λμ΄μΌ νλ μ§ μκ°νκΈ°
- Prefer more precise forms of any such as any[] or {[id: string]: any} or () => any if they more accurately model your data.
- κ·Έλ₯ anyλ³΄λ€ μ λ°ν ννλ₯Ό λͺ¨λΈλ§νκΈ°.
- anyλ₯Ό μ¬μ©ν ꡬ체μ μΈ νν: any[], any[][], {[id: string]: any}, Record<string, any>, () => any
μμ΄ν
40: ν¨μ μμΌλ‘ νμ
λ¨μΈλ¬Έ κ°μΆκΈ° Hide Unsafe Type Assertions in Well-Typed Functions
- μΈλΆ νμ
μ μλ κ°λ¨νμ§λ§, ν¨μ λ΄λΆ λ‘μ§μ΄ 볡μ‘ν κ²½μ°!
- λ΄λΆμ νμ λ¨μΈμ μ¬μ©νκ³ , μΈλΆλ‘ λλ¬λλ νμ μ μλ₯Ό μ νν λͺ μ
- νλ‘μ νΈμ νμ λ¨μΈλ¬Έμ΄ λλ¬λ μμ§ μλλ‘ κ°μΆκΈ°