2024-06-05.md

🏑

DIL: μ΄νŽ™ν‹°λΈŒ νƒ€μž…μŠ€ν¬λ¦½νŠΈ

μŠ€ν„°λ””: μ›”κ°„ CS, https://github.com/monthly-cs/2024-05-effective-typescript
μž‘μ„±μΌ: 2024-06-05
μž‘μ„±μž: dusunax


μ•„μ΄ν…œ 41: any의 진화λ₯Ό μ΄ν•΄ν•˜κΈ° Understand Evolving Types

  • 일반적인 νƒ€μž…: λ³€μˆ˜μ˜ νƒ€μž…μ€ λ³€μˆ˜λ₯Ό μ„ μ–Έν•  λ•Œ κ²°μ • > 이후 정체
  • any: 이브이
function range(start: number, limit: number) {
  const nums = [];
  //    ^? const nums: any[]
  for (let i = start; i < limit; i++) {
    nums.push(i);
    // ^? const nums: any[]
  }
  return nums;
  //     ^? const nums: number[]
  // number 값을 λ„£λŠ” μˆœκ°„ μ§„ν™”ν•œλ‹€
}
  • νƒ€μž… 쒁히기 type narrowing 와 λ‹€λ₯Έ 점 => 배열에 λ‹€μ–‘ν•œ νƒ€μž…μ˜ μš”μ†Œλ₯Ό λ„£μœΌλ©΄ νƒ€μž…μ΄ ν™•μž₯되며 μ§„ν™”ν•œλ‹€
const result = [];
//    ^? const result: any[]
result.push("a");
result;
// ^? const result: string[]
result.push(1);
result;
// ^? const result: (string | number)[]
  • μ΄ˆκΈ°κ°’μ΄ null인 κ²½μš°λ„ any 진화. try/catch 블둝 μ•ˆμ—μ„œ λ³€μˆ˜λ₯Ό ν• λ‹Ήν•˜λŠ” κ²½μš°μ— 보톡 λ‚˜νƒ€λ‚¨
let value = null;
//  ^? let value: any
try {
  value = doSomethingRiskyAndReturnANumber();
  value;
  // ^? let value: number
} catch (e) {
  console.warn("alas!");
}
value;
// ^? let value: number | null
// 진화
  • if else문의 경우
let value;
//  ^? let value: any
if (Math.random() < 0.5) {
  value = /hello/;
  value;
  // ^? let value: RegExp
} else {
  value = 12;
  value;
  // ^? let value: number
}
value;
// ^? let value: number | RegExp
// 진화함

νŠΉμ§•

  • any νƒ€μž… μ§„ν™”λŠ” κ°€ μ•”μ‹œμ  anyμ—μ„œ 적용되며, λͺ…μ‹œμ  anyλŠ” μœ μ§€λœλ‹€.
  • 값을 ν• λ‹Ήν•˜κ±°λ‚˜, 배열에 μš”μ†Œλ₯Ό 넣은 ν›„μ—λ§Œ μΌμ–΄λ‚˜κΈ° λ•Œλ¬Έμ— => νŽΈμ§‘κΈ°μ—μ„œ μ΄μƒν•˜κ²Œ 보일 수 μžˆλ‹€. (할당이 μΌμ–΄λ‚œ μ€„μ˜ νƒ€μž…μ„ 쑰사해도 any. 할당이 λλ‚œ ν›„, 진화)
  • μ–΄λ– ν•œ 할당도 ν•˜μ§€ μ•Šκ³  μ‚¬μš©ν•˜λ©΄ noImplicitAny 였λ₯˜
    • μ•”μ‹œμ  any μƒνƒœμΌ λ•Œ 값을 읽으렀 ν•˜λ©΄ 였λ₯˜κ°€ λ°œμƒν•œλ‹€.

ν•¨μˆ˜ ν˜ΈμΆœμ„ 거쳐도 μ§„ν™”ν•˜μ§€ μ•ŠλŠ”λ‹€

  • μ•„λž˜ μ˜ˆμ‹œμ—μ„œ .forEach ν•¨μˆ˜ ν˜ΈμΆœμ„ 거쳀을 λ•Œ μ§„ν™”ν•˜μ§€ μ•ŠμŒ
  • forEach둜 μˆœν™”ν•˜λŠ” λŒ€μ‹ , λ°°μ—΄μ˜ mapκ³Ό filter λ©”μ„œλ“œλ‘œ 단일 ꡬ문으둜 λ°°μ—΄ 생성 => any 전체λ₯Ό μ§„ν™”μ‹œν‚€λŠ” 방법 생각
function makeSquares(start: number, limit: number) {
  const nums = [];
  //    ~~~~ Variable 'nums' implicitly has type 'any[]' in some locations
  range(start, limit).forEach((i) => {
    nums.push(i * i); // μ§„ν™”ν•˜μ§€ μ•ŠλŠ”λ‹€
  });
  return nums;
  //     ~~~~ Variable 'nums' implicitly has an 'any[]' type
}

진화 방식?

  • 일반적인 λ³€μˆ˜κ°€ μΆ”λ‘ λ˜λŠ” 원리와 λ™μΌν•˜λ‹€.
  • μ§„ν™”ν•œ λ°°μ—΄μ˜ νƒ€μž…μ΄ (string|number)[]일 λ•Œ, number[]이어야 ν•˜λŠ” 데 string이 μ„žμ˜€μ—¬μ„œ μ§„ν™”ν–ˆμ„ κ°€λŠ₯성도 μžˆλ‹€.
  • λ”°λΌμ„œ λͺ…μ‹œμ  νƒ€μž… ꡬ문이 더 μ•ˆμ „μ„± μžˆλŠ” 쒋은 섀계

Things to Remember

  • While TypeScript types typically only refine, the types of values initialized to null, undefined, or [] are allowed to evolve.
    • 일반적으둜 νƒ€μž…μ€ μ •μ œλ§Œ λ˜μ§€λ§Œ, μ•”μ‹œμ  Any인 경우 (null, undefined, []둜 μ΄ˆκΈ°ν™”λœ 경우) μ§„ν™”ν•œλ‹€
  • Recognize and understand this construct where it occurs, and use it to reduce the need for type annotations in your own code.
    • 이런 λ™μž‘μ΄ 일어남을 μ•Œκ³  있으면, ν•„μš”ν•œ 경우 νƒ€μž… ꡬ문을 쀄일 수 μžˆλ‹€.
  • For better error checking, consider providing an explicit type annotation instead of using evolving types.
    • μ—λŸ¬ 체킹과 μ•ˆμ •μ„±μ„ μœ„ν•΄μ„œλŠ”, νƒ€μž…μ„ 진화 μ‹œν‚€λŠ” 것보닀 λͺ…μ‹œμ μΈ νƒ€μž… ꡬ문을 μ‚¬μš©ν•˜λŠ” 것이 λ‚«λ‹€.