"타입은 완성된 JavaScript 위에 붙이는 영수증이 아니라, 만들 시스템의 가능한 세계를 먼저 그리는 도구야."
주석에서 설계 표면으로
처음에는 TypeScript를 'JavaScript에 타입 주석을 더한 것'으로 느끼기 쉬워. 익숙해지면 질문의 순서가 바뀐다. 어떤 데이터가 들어오고, 어떤 상태가 가능하며, 함수 사이에 무엇을 보존해야 하는지 먼저 타입으로 스케치하게 돼.
그렇다고 구현 전에 모든 타입을 완벽하게 설계하라는 뜻은 아니야. 작은 실행 조각과 타입을 번갈아 다듬으며 도메인 이해가 바뀔 때 계약도 고쳐야 해. 타입이 현실보다 앞서 독자적인 퍼즐이 되면 멈춰.
불가능한 상태 줄이기
로딩 중인데 데이터와 오류가 동시에 존재하는 객체보다 loading | ready | failed 판별 합집합이 의도를 잘 보여 줘. 공개 함수의 인자와 반환 타입은 호출자가 무엇을 준비하고 무엇을 기대할 수 있는지 드러내.
유효성 검사가 필요한 외부 값은 unknown에서 시작하고, 한 번 증명한 관계는 제네릭과 타입 가드로 보존해. 좋은 타입 설계는 주석을 많이 쓰는 일이 아니라 잘못된 조합을 적게 만드는 일이야.
객체 지향 원칙과 만나는 자리
캡슐화는 클래스의 private에만 있지 않아. 모듈이 내부 타입을 내보내지 않는 것도 캡슐화고, 인터페이스로 소비자가 필요한 능력만 보는 것도 추상화야. 제네릭은 여러 구체 타입에 같은 관계를 적용하고, 구조적 타입은 구현보다 모양에 의존하게 해.
상속이 언제나 좋은 객체 설계가 아니듯 복잡한 조건부 타입도 언제나 좋은 타입 설계는 아니야. 변경 이유가 같은 것을 묶고, 다른 것을 분리한다는 원칙이 두 층에 모두 적용돼.