타입스크립트에서는 변수에 값을 할당하고 타입을 부여하는 방법은 두가지입니다.
interface Person {name : string};
const alice : Person = {name : 'Alice'} //타입은 Person
const bob = {name : 'Bob'} as Person //타입은 Person
✅ 타입 단언보다 타입 선언을 사용하는 게 낫습니다.
const alice : Person = {
name : 'Alice',
occupation : 'TypeScript developer'
// ~~~~ 개체 리터럴은 알려진 속성만 지정할 수 있으며
// 'Person' 형식에 'occupation'이(가) 없습니다.
};
const bob = {
name : 'Bob',
occupation : 'JavaScript developer'
} as Person; // 오류 없음
타입 선언문에는 잉여 속성 체크
가 동작했지만, 단언문에는 적용되지 않습니다.
화살표 함수의 타입 선언은 추론된 타입이 모호할 때가 있습니다.
const people = ['alice', 'bob', 'jan'].map(name => ({name}));
// Person[]을 원했지만 결과는 {name : string;}[]...
타입 단언을 사용하면 문제가 해결되는 것처럼 보이지만, 런타임에 문제가 발생할 수 있습니다.
const people = ['alice', 'bob', 'jan'].map(name => ({name} as Person));
// 타입은 Person[]
// 런타임에서 문제가 발생할 수 있음
const people = ['alice', 'bob', 'jan'].map(name => ({} as Person));
// 오류없음
단언문을 사용하지 않고 화살표 함수 안에 타입과 함께 변수를 선언하는 것이 가장 직관적입니다.
const people = ['alice', 'bob', 'jan'].map(name => (
const person:Person = {name};
return person
)); // 타입은 Person[]
// 간결한 코드를 위해 변수 대신 화살표 함수의 반환 타입을 선언
const people = ['alice', 'bob', 'jan'].map(
(name):Person => ({name})
); // 타입은 Person[]'
(name): Person
은 name에 타입이 없고 반환 타입이 Person
임을 명시합니다.
(name: Person)
은 name의 타입이 Person
임을 명시하고 반환 타입은 없기 때문에 오류가 발생합니다.
최종적으로 원하는 타입을 직접 명시하고, 타입스크립트가 할당문의 유효성 검사하게 합니다.
const people: Person[] = ['alice', 'bob', 'jan'].map(
(name):Person => ({name})
); // 타입은 Person[]'
타입스크립트는 DOM에 접근할 수 없습니다.
자주쓰이는 특별한 문법(!)을 사용하여 null이 아님을 단언하는 경우도 있습니다.
const elNull = document.getElementById('foo'); //타입은 HTMLElement | null
const el = document.getElementById('foo'); //타입은 HTMLElement
단언문은 컴파일 과정 중에 제거되므로, 타입 체커는 알지 못하지만 그 값이 null이 아니라고 확신할 수 있을때 사용해야 합니다.
타입 단언문으로 임의의 타입 간에 변환을 할 수는 없습니다.
A가 B의 부분집합인 경우에 타입 단언문을 사용해 변환할 수 있습니다.
➡ HTMLElement는 HTMLElement | null의 서브타입이기 때문에 이러한 타입 단언은 동작
interface Person { name: string; }
const body = document.body;
const el = body as Person;
// 형식이 충분히 겹치지 않기 때문에 실수로 판단, 의도적인 경우 먼저 식을 unknown으로 변환하세요.
const el = body as unknown as Person;