LittleDeveloper

νƒ€μž… 단언은 μœ„ν—˜ν•΄? - ‘as’, μ•Œκ³  μ“°μž! λ³Έλ¬Έ

typescript

νƒ€μž… 단언은 μœ„ν—˜ν•΄? - ‘as’, μ•Œκ³  μ“°μž!

lemonjelly 2023. 4. 6. 19:49

πŸ§νƒ€μž… 단언은 μ™œ λ“±μž₯ν–ˆλŠ”κ°€?

  • νƒ€μž…μŠ€ν¬λ¦½νŠΈ μ»΄νŒŒμΌλŸ¬λŠ” νƒ€μž… ν‘œκΈ°, νƒ€μž… 쒁히기(type narrowing)와 νƒ€μž… μΆ”λ‘  λ“±μ˜ 기법을 μ΄μš©ν•΄ κ°’μ˜ νƒ€μž…μ„ νŒλ‹¨ν•œλ‹€.

κ·ΈλŸ¬λ‚˜ 컴파일러의 정보 λŒ€μ‹ , ν”„λ‘œκ·Έλž˜λ¨Έκ°€ μ›ν•˜λŠ” νƒ€μž…μ„ 값에 ν• λ‹Ήν•˜κ³  μ‹Άλ‹€λ©΄?

  • μœ„μ˜ 경우λ₯Ό μœ„ν•΄ λ“±μž₯ν•œ 것이 νƒ€μž… 단언(type assertion)이닀.

πŸ”Žνƒ€μž… 단언(Type Assertion)μ΄λž€ 무엇인가?

  • νƒ€μž… 단언은 μ•„λž˜μ™€ 같은 ν˜•νƒœλ‘œ 이루어진닀.

value as Type

  • μ•„λž˜μ˜ μ½”λ“œλ‘œ νƒ€μž… λ‹¨μ–Έμ˜ μ˜ˆμ‹œλ₯Ό ν™•μΈν•΄λ³΄μž.
interface Dog {
  legs: 4;
  bark(): void;
}

interface Insect {
  legs: number;
  creepy: boolean;
}

interface Fish {
  swim(): void;
}

type Animal = Dog | Insect | Fish;

function doSomethingWithAnimal(animal: Animal) {
  (animal as Fish).swim();
} 
  • DogλΌλŠ” 객체 νƒ€μž…, InsectλΌλŠ” 객체 νƒ€μž…, FishλΌλŠ” 객체 νƒ€μž…μ΄ μžˆλ‹€.
  • 동물은 μ΄λ ‡κ²Œ 3가지 νƒ€μž…μ΄ μžˆλ‹€.
  • doSomethingWithAnimal μ΄λΌλŠ” ν•¨μˆ˜λŠ” μ–΄λ–€ κΈ°λŠ₯을 ν•˜κ³  μžˆλŠ”μ§€ μ‚΄νŽ΄λ³΄λ©΄,
    • 이 ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜μΈ animal 객체λ₯Ό Fish νƒ€μž…μ΄λΌκ³  λ‹¨μ–Έν•œλ‹€.
      • Fish라고 λ‹¨μ–Έλœ animal κ°μ²΄λŠ”, swimμ΄λΌλŠ” λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€. (Fish인 경우만 swimν•  수 μžˆλ‹€κ³  κ°€μ •ν•˜λŠ” λ§₯λ½μž„.)

μ˜ˆμƒλ˜λŠ” λ¬Έμ œμ—λŠ” μ–΄λ–€ 것이 μžˆμ„κΉŒ?

  • doSomethingWithAnimalμ΄λΌλŠ” ν•¨μˆ˜μ— Dog λ˜λŠ” Insect νƒ€μž…μ„ λ„£μ–΄μ£Όλ©΄, 각각의 νƒ€μž…μœΌλ‘œ 된 κ°μ²΄λŠ” swimμ΄λΌλŠ” κΈ°λŠ₯(λ©”μ„œλ“œ)λ₯Ό μ‚¬μš©ν•  수 μ—†μœΌλ―€λ‘œ, 였λ₯˜κ°€ λ°œμƒν•  것이닀.

βœ”νƒ€μž… 단언은, νƒ€μž… μ—λŸ¬κ°€ μ‚¬λΌμ§ˆ 뿐 λŸ°νƒ€μž„ μ—λŸ¬λŠ” 막아주지 μ•ŠλŠ”λ‹€.


νƒ€μž… 단언에 λŒ€ν•œ λ§ˆμŒκ°€μ§…

  • 개발자: 이 값이 μ–΄λ–€ νƒ€μž…μΈμ§€λŠ” λ‚΄κ°€ κ°€μž₯ 잘 μ•Œμ•„! or λ‚΄κ°€ μ •ν•  κ±°μ•Ό!
    • μ΄λŸ¬ν•œ μ˜λ„λ₯Ό νƒ€μž…μ„ λ‹¨μ–Έν•˜λ©΄, νƒ€μž… λ‹¨μ–ΈμœΌλ‘œ μΈν•œ μ—λŸ¬ μ—­μ‹œ 개발자의 μ±…μž„μ΄ λœλ‹€.
  • νƒ€μž… μ„ μ–Έμ—μ„œ 잘λͺ»λœ νƒ€μž…μ˜ 값이 ν• λ‹Ήλ˜λ©΄, νƒ€μž… 체컀가 μΉœμ ˆν•˜κ²Œ 였λ₯˜λ₯Ό λ‚΄λΏœλŠ”λ‹€.
    • μ΄λŸ¬ν•œ μΉœμ ˆν•¨μ„ λ¬΄μ‹œν•˜κ³  νƒ€μž…μ„ μ§€μ •ν•˜λŠ” 것은, 항상 μ˜³μ§€ μ•Šμ€ 방식인가?
    즉, νƒ€μž… 단언은 지양해야 ν•˜λŠ” 것인가?### νƒ€μž… 단언이 ν•„μš”ν•œ κ²½μš°λ„ μžˆμ„κΉŒ?
  • ### 지양해야 ν•œλ‹€λ©΄, μ–΄λ– ν•œ κ²½μš°κ°€ μžˆμ„κΉŒ?

βš νƒ€μž… μ„ μ–ΈμœΌλ‘œ μΆ©λΆ„ν•œ 경우, νƒ€μž… 단언 ν”Όν•˜κΈ°

  • νƒ€μž… 선언을 톡해 νƒ€μž… 체컀가 μ–΄λ–€ νƒ€μž…μΈμ§€ λͺ…ν™•νžˆ μΆ”λ‘ ν•  수 μžˆλ‹€λ©΄, νƒ€μž… 단언을 μ‚¬μš©ν•  μ΄μœ κ°€ μ—†λ‹€.

νƒ€μž… μ„ μ–Έ μ˜ˆμ‹œ - ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ νƒ€μž… μ„ μ–Έ

  • ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ νƒ€μž… 선언은 μΆ”λ‘ λœ νƒ€μž…μ΄ λͺ¨ν˜Έν•  수 μžˆλ‹€.
  • μ•„λž˜ μ½”λ“œμ—μ„œ Person interfaceλ₯Ό μ‚¬μš©ν•˜κ³  μ‹Άλ‹€κ³  ν•΄λ³΄μž.
interface Person { name: string };

const people = ['alice', 'bob', 'jan'].map(name => ({name});
// Person[]을 μ›ν–ˆμ§€λ§Œ κ²°κ³ΌλŠ” { name: string; } []...
  • κ·Έλ ‡λ‹€λ©΄ μ–΄λ–€ μ‹μœΌλ‘œ μ½”λ“œλ₯Ό μ§œμ•Ό ν• κΉŒ?
    • νƒ€μž… λ‹¨μ–ΈμœΌλ‘œ ν•΄κ²°ν•œλ‹€λ©΄?
    interface Person { name: string };
    const people = ['alice', 'bob', 'jan'].map(
      name => ({name} as Person)
    ); // Type is Person[]
    
    • 단, μœ„μ™€ 같은 단언문 방식은 λŸ°νƒ€μž„ μƒμ—μ„œ 였λ₯˜κ°€ λ°œμƒν•  수 μžˆλ‹€.
    • κ·ΈλŸ¬λ―€λ‘œ 단언문을 쓰지 μ•Šκ³ , μ•„λž˜μ™€ 같이 ν™”μ‚΄ν‘œ ν•¨μˆ˜ λ‚΄μ—μ„œ νƒ€μž…κ³Ό ν•¨κ»˜ λ³€μˆ˜λ₯Ό μ§κ΄€μ μœΌλ‘œ μ„ μ–Έν•΄λ³΄μž!
const people = ['alice', 'bob', 'jan'].map(name => {
	const person: Person = {name};
	return person
});   // νƒ€μž…μ€ Person[]
  • λ˜λŠ” λ³€μˆ˜ λŒ€μ‹  ν•¨μˆ˜μ˜ λ°˜ν™˜ νƒ€μž…μ„ μ„ μ–Έν•  수 μžˆλ‹€!
const people: Person[] = ['alice', 'bob', 'jan'].map(name => {
	(name): Person => ({name})
}); 
  • λ”°λΌμ„œ νƒ€μž… 단언이 κΌ­ ν•„μš”ν•œ κ²½μš°κ°€ μ•„λ‹ˆλΌλ©΄, μ•ˆμ •μ„± 체크가 λ˜λŠ” νƒ€μž… 선언을 μ‚¬μš©ν•˜λŠ” 것이 λ°”λžŒμ§ν•˜λ‹€.

βœ¨νƒ€μž… 단언은 μ–Έμ œ ν•„μš”ν•œκ°€?

βœ…νƒ€μž… 정보λ₯Ό κ°œλ°œμžκ°€ 더 잘 μ•„λŠ” 경우

  1. DOM Element
  • DOM ElementλŠ” νƒ€μž…μŠ€ν¬λ¦½λ³΄λ‹€ μš°λ¦¬κ°€ 더 잘 μ•„λŠ” 정보이닀.
  • νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” DOM에 μ ‘κ·Όν•  수 μ—†κΈ° λ•Œλ¬Έμ—, νƒ€μž… 단언을 μ“°λŠ” 것이 νƒ€λ‹Ήν•˜λ‹€.
  • μ•„λž˜μ™€ 같이 λ²„νŠΌ 객체에 μ ‘κ·Όν•  λ•Œ, 이 λ²„νŠΌμ„ as HTMLButtonElement λΌκ³  λ‹¨μ–Έν•΄μ£ΌλŠ” 것이 μ’‹λ‹€.
document.querySelector('#myButton').addEventListener('click', e => {
  e.currentTarget // Type is EventTarget
  const button = e.currentTarget as HTMLButtonElement;
  button // Type is HTMLButtonElement
});
  • λ˜λŠ” ! λ₯Ό μ΄μš©ν•΄ null이 μ•„λ‹˜μ„ 단언해쀄 μˆ˜λ„ μžˆλ‹€.
const elNull = document.getElementById('foo');  // Type is HTMLElement | null
const el = document.getElementById('foo')!; // Type is HTMLElement

βœ…3쀄 μš”μ•½

νƒ€μž… λ‹¨μ–Έλ³΄λ‹€λŠ” νƒ€μž… 선언을 μ‚¬μš©ν•˜μž.

TS보닀 더 잘 μ•„λŠ” νƒ€μž…μ΄λΌλ©΄ νƒ€μž… 단언을 μ‚¬μš©ν•˜μž.

asλ‚˜ ! λ₯Ό μ‚¬μš©ν•˜μ—¬ νƒ€μž… 단언을 ν•œλ‹€.