Skip to main content

타입단언보다 타입선언을 사용하자(feat. DOM element는 좀 다름)

  • 타입선언: 할당되는 값이 해당 인터페이스에 만족하는지 검사
  • 타입단언: 강제로 타입 지정 => 타입체커에게 오류를 무시하라고 하는 것

(타입스크립트가 추론한 타입이 있더라도 Person 타입으로 간주)

interface Person {
name: string;
// occupation : string
}

const alice: Person = {
name: "Alice",
occupation: "TypeScript Developer",
};
/**
Type '{ name: string; occupation: string; }' is
not assignable to type 'Person'.
Object literal may only specify known properties,
and 'occupation' does not exist in type 'Person'.(2322)
**/
const alice2 = {
name: "Alice",
occupation: "TypeScript Developer",
} as Person;

/*
오류 없음
*/

하지만 DOM Element는 타입스크립트보다 우리가 더 정확할 때가 있음

=> 왜냐하면 타입스크립트의 타입체커는 DOM에 접근하지 못해서, 지금 ref를 잡은 element가 어떤 태그인지모름

따라서 이때는 타입단언을 쓰는 것이 타당함

interface Person {
name: string;
}

const body = document.body;

const el = body as Person;
/**
Conversion of type 'HTMLElement' to type 'Person' may be a mistake
because neither type sufficiently overlaps with the other.
If this was intentional, convert the expression to 'unknown' first.

Property 'name' is missing in type 'HTMLElement' but required in type 'Person'.(2352)
**/// ----------// HTMLButtonElement는 HTMLElement | null의 서브타입이라 단언이 됨const el = body as HTMLButtonElement;

// Person은 HTMLElement | null의 서브타입이 아니기 때문에 단언이 안됨const el = body as Person;

// ----------
/**
unknown을 써주면됨 (물론 추후에 고쳐야하는 타입)
임시방편
**/
const el = body as unknown as Person
// HTMLElement | nullconst el = document.getElementById('id');

/**
뒤의 ! 를 이용해서 해당 DOM이 null이 아니라고 타입 단언
*/
const el = document.getElementById("id")!;