이펙티브 타입스크립트 (댄 밴더캄 지음) 를 읽고 정리
📍요약
✅객체의 프로퍼티를 제각각 추가하지 말고 한번에 객체를 만들어야 한다
✅안전한 타입으로 프로퍼티를 추가하려면 스프레드 연산자를 활용한다
📍객체를 만들때 프로퍼티를 나중에 추가하면 안된다
한번 정해진 타입은 잘 변경되지 않는다
- 따라서 객체를 만들고 프로퍼티를 나중에 추가하면 타입이 변경됨
⭐모든 프로퍼티를 갖춰 한 번에 객체를 생성해야 함- 예시
const pt = {}; // 타입이 {} -> 아무 프로퍼티도 존재 X
pt.x = 3;
// ~ Property 'x' does not exist on type '{}'
pt.y = 4;
// ~ Property 'y' does not exist on type '{}'
// 인터페이스를 미리 만들고 할당해도 에러 위치만 바뀔 뿐 해결 x
interface Point { x: number; y: number; }
const pt2: Point = {};
// ~~ Type '{}' is missing the following properties from type 'Point': x, y
pt2.x = 3;
pt2.y = 4;
📍프로퍼티를 나중에 추가해야 한다면 타입 단언문(as)을 이용한다
- 예시
interface Point { x: number; y: number; }
const pt = {} as Point;
pt.x = 3;
pt.y = 4; // OK
📍타입스크립트에서도 스프레드 연산자를 사용해야 하는 이유
- 스프레드 연산자 대신 Object.assign 이용 => 타입에러 발생
interface Point { x: number; y: number; }
const pt = {x: 3, y: 4};
const id = {name: 'Pythagoras'};
const namedPoint = {};
Object.assign(namedPoint, pt, id); // array의 concat과 동일
namedPoint.name;
// ~~~~ Property 'name' does not exist on type '{}'
console.log(namedPoint); // 런타임 에러는 없음
// {
// "x": 3,
// "y": 4,
// "name": "Pythagoras"
// }
- 스프레드 연산자 이용 => 타입에러 없음
interface Point { x: number; y: number; }
const pt = {x: 3, y: 4};
const id = {name: 'Pythagoras'};
const namedPoint = {...pt, ...id};
namedPoint.name; // OK, type is string
console.log(namedPoint);
// {
// "x": 3,
// "y": 4,
// "name": "Pythagoras"
// }
📍타입 안정성을 유지하며 옵셔널 프로퍼티 추가하기
- 일회용 null 또는 {} (빈 객체) 에 스프레드 연산자를 활용한다
declare let hasMiddle: boolean; // declare 키워드가 있으면 컴파일 안하겠다는 의미
// JS 코드에서 TS 문법을 사용하기 위해 그냥선언해주는 것
const firstLast = {first: 'Harry', last: 'Truman'};
const president = {...firstLast, ...(hasMiddle ? {middle: 'S'} : {})};
// president의 타입
// {
// middle?: string | undefined; -> 옵셔널
// first: string;
// last: string;
// }
📍declare 키워드
declare 키워드는 타입스크립트에 이 부분은 컴파일이 필요없다고 알린다
- 그래서 실행하려고 해도 에러 발생
단지 다른 코드에서 참조할 수 있게 돕는 역할을 수행