interface Person { name: string };
const alice: Person = { name: 'Alice' }; //타입 선언
const bob = { name: 'Bob' } as Person; // 타입 단언
const alice: Person = {};
// ~~~~~ 'Person' 유형에 필요한 'name' 속성이 '{}' 유형에 있습니다.
const bob = {} as 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 => ({} as Person)); // 오류 없음
name의 타입과 반환하는 타입을 직접 명시해서 해결할 수 있습니다.
const people: Person[] = ["alice", "bob", "jan"].map(
(name): Person => ({ name })
);
document.querySelector('#myButton').addEventListener('click', e => {
e.currentTarget // 타입은 EventTarget
const button = e.currentTarget as HTMLButtonElement;
button // 타입은 HTMLButtonElement
});
타입 스크립트 Dom에 접근할 수 없기 때문에 버튼엘리먼트를 알지 못합니다. 우리는 타입스크립트가 알지 못하는 정보를 가지고 있기때문에 여기서는 타입단언문을 사용하는것이 타당합니다.
(!)을 사용해서 null이 아님을 단언할 수 있습니다.
const elNull = document.getElementById('foo'); // 타입 HTMLElement | null
const el = document.getElementById('foo')!; // 타입 HTMLElement
타입스크립트는 기본형과 객체 래퍼 타입을 별도로 모델링합니다.
기본 , 객체 래퍼
string, String
number, Number
boolean, Boolean
symbol, Symbol
bigint, BigInt
기본형은 객체타입에 할당 가능하지만 반대로는 할 수 없습니다.
타입스크립트는 객체 래퍼 타입을 지양하고, 대신 기본형 타입을 사용해야 합니다.
객체 리터럴을 변수에 할당하거나 함수에 매개변수로 전달할 때 잉여 속성 체크가 수행됩니다.
interface Room {
numDoors: number;
ceilingHeightFt: number;
}
const r: Room = {
numDoors: 1,
ceilingHeightFt: 10,
elephant: "present", // 객체 리터럴은 알려진 속성만 지정할 수 있으며, Room에 'elephant'가 없습니다.
};
임시 변수 obj를 도입해 보면 알 수 있습니다.
obj는 { numDoors: number;
ceilingHeightFt: number;
elephant: string;}
으로 타입이 추론됩니다.
임시 변수를 사용하여 잉여 속성 체크를 건너뛸 수 있습니다.
const obj = {
numDoors: 1,
ceilingHeightFt: 10,
elephant: "present",
};
const r: Room = obj;
obj 타입은 room의 부분 집합을 포함하므로, 할당가능하며 타입 체커도 통과합니다.
위의 예제 중에 첫번째 예제에서는, 구조적 타입 시스템에서 발생할 수 있는 중요한 종류의 오류를 잡을 수 있도록 '잉여 속성 체크'라는 과정이 수행되었습니다.
인덱스 시그니처를 사용해서 추가적인 속성을 예측하게 해도 됩니다.
interface Options {
darkMode?: boolean;
[otherOptions: string]: unknown;
}
const o: Options = { darkmode: true }; // 정상
선택적 속성만 가지는 약한 타입에서도 비슷한 체크가 동작합니다.
interface LineChartOptions {
logscale?: boolean;
invertedYAxis?: boolean;
areaChart?: boolean;
}
const opts = { logScale: true };
const o: LineChartOptions = opts; // 'LineChartOptions'에 '{ logScale: boolean; }' 속성이 없음
<이펙티브 타입스크립트> (댄 밴더캅 지음, 장원호 옮김, 인사이트, 2021)