TypeScript Reference
TypeScript 타입 시스템 레퍼런스
TypeScript Reference 소개
TypeScript 레퍼런스는 기본부터 고급 패턴까지 TypeScript 타입 시스템을 검색할 수 있는 치트 시트입니다. 원시 타입(string, number, boolean), 배열, 튜플, 유니온과 인터섹션 타입, 리터럴 타입, 열거형, 타입 단언 등 JavaScript에 정적 타이핑을 추가하는 기본 구성 요소를 포함합니다. any와 unknown의 구분, void, never, null 같은 특수 타입도 다룹니다.
이 레퍼런스는 기본타입, 인터페이스, 제네릭, 유틸리티타입, 타입가드, 데코레이터, 모듈, 설정의 8개 카테고리에 걸쳐 60개 이상의 항목을 체계적으로 정리합니다. 제네릭 섹션은 제네릭 함수, 인터페이스, extends를 사용한 제약 조건, keyof와 typeof 연산자, infer를 사용한 조건부 타입, 매핑된 타입, 템플릿 리터럴 타입을 다룹니다. 유틸리티타입 섹션은 Partial, Required, Pick, Omit, Record, Readonly, Exclude, Extract, NonNullable, ReturnType, Parameters를 설명합니다.
타입 정의 외에도 typeof, instanceof, in, is 구문을 사용한 커스텀 타입 프레디케이트 등 타입 가드 기법을 다룹니다. 완전한 switch문을 위한 kind 패턴의 판별 유니온, 타입 확장 없이 타입 안전한 객체 검증을 위한 satisfies 연산자, 클래스와 메서드 데코레이터, 트리 셰이킹을 위한 타입 전용 임포트가 있는 ES 모듈, 선언 병합, 네임스페이스, strict 모드와 경로 별칭을 위한 핵심 tsconfig.json 설정을 포괄합니다.
주요 기능
- 완전한 원시 타입 레퍼런스: string, number, boolean, 배열, 튜플, 유니온, 인터섹션, 리터럴, 열거형 타입
- 인터페이스 패턴: 정의, extends, 인덱스 시그니처, 함수 인터페이스, type vs interface 비교
- 제네릭: 함수, 인터페이스, 제약 조건, keyof/typeof, infer, 조건부 타입, 매핑된 타입, 템플릿 리터럴
- 모든 내장 유틸리티 타입: Partial, Required, Pick, Omit, Record, Readonly, Exclude, Extract, NonNullable, ReturnType, Parameters
- 타입 가드 기법: typeof, instanceof, in 연산자, 커스텀 타입 프레디케이트(is), kind를 사용한 판별 유니온
- 구체적인 타입 추론을 잃지 않고 타입을 검증하는 satisfies 연산자 (TS 4.9+)
- 모듈 시스템: import/export, 타입 전용 임포트, 선언 병합, 네임스페이스
- tsconfig.json 설정: strict 모드 옵션, baseUrl을 사용한 경로 별칭, 컴파일러 설정
자주 묻는 질문
TypeScript에서 type과 interface의 차이점은 무엇인가요?
둘 다 객체 형태를 정의하지만 핵심적인 차이가 있습니다. 인터페이스는 선언 병합을 지원하여(같은 이름의 여러 인터페이스 선언이 자동으로 결합됨) 사용자가 확장해야 할 수 있는 라이브러리 API에 이상적입니다. 타입은 유니온 타입(type ID = string | number), 인터섹션 타입, 매핑된 타입, 조건부 타입을 지원합니다. 일반적인 관례는 공개 API 계약에 인터페이스를, 유니온, 유틸리티 타입, 내부 정의에 타입을 사용하는 것입니다.
any 대신 unknown을 언제 사용해야 하나요?
타입이 불확실한 값을 받지만 타입 안전성을 유지하고 싶을 때 unknown을 사용합니다. 모든 타입 검사를 비활성화하는 any와 달리, unknown은 작업을 수행하기 전에 타입을 좁혀야 합니다. 예를 들어 unknown 값에 .toUpperCase()를 호출하려면 typeof로 문자열인지 확인해야 합니다. 이것이 API 응답이나 사용자 입력 같은 외부 소스의 값에 대한 타입 안전한 대안입니다.
extends를 사용한 제네릭 제약 조건은 어떻게 작동하나요?
제네릭 제약 조건은 extends를 사용하여 타입 인자로 전달할 수 있는 타입을 제한합니다. 예를 들어 <T extends HasLength>는 T가 length 속성을 가져야 합니다. 이를 통해 문자열, 배열, 또는 length 속성이 있는 모든 객체를 받아들이되 length가 없는 number 같은 타입은 거부하는 함수를 작성할 수 있습니다. 제약 조건에 keyof도 사용 가능합니다: <K extends keyof T>는 K를 T의 유효한 속성 이름으로 제한합니다.
판별 유니온이란 무엇이고 언제 사용하나요?
판별 유니온은 각 멤버가 TypeScript가 타입 좁히기에 사용하는 공통 리터럴 속성(판별자)을 가진 유니온 타입입니다. 예: type Shape = { kind: "circle"; radius: number } | { kind: "rect"; width: number; height: number }. s.kind에 대한 switch에서 TypeScript는 각 case 분기의 정확한 타입을 알 수 있습니다. 상태 머신, 리듀서의 액션 타입, 유한한 변형 집합이 있는 모든 시나리오에 이 패턴을 사용하세요.
Partial, Pick, Omit 유틸리티 타입은 어떻게 작동하나요?
Partial<T>는 모든 속성을 선택적으로 만들어 일부 필드만 변경하는 업데이트 함수에 유용합니다. Pick<T, K>는 선택한 속성만 가진 타입을 만듭니다: Pick<User, "name" | "age">는 { name: string; age: number }을 제공합니다. Omit<T, K>는 반대로, 지정한 속성을 제외한 모든 속성을 가진 타입을 만듭니다. 조합도 가능합니다: Partial<Pick<User, "name" | "email">>은 name과 email이 모두 선택적인 타입을 만듭니다.
satisfies 연산자는 무엇을 하나요?
satisfies 연산자(TypeScript 4.9+)는 추론된 타입을 확장하지 않으면서 값이 타입과 일치하는지 검증합니다. 예를 들어 const palette = { red: [255, 0, 0], green: "#00ff00" } satisfies Record<string, string | number[]>는 palette가 Record 타입과 일치하는지 확인하지만, palette.red는 여전히 number[](string | number[]가 아님)로 추론되어 .map()을 호출할 수 있습니다. satisfies 없이는 구체적인 타입 정보를 잃게 됩니다.
타입 전용 임포트는 번들 크기를 어떻게 개선하나요?
타입 전용 임포트(import type { User } from "./types")는 컴파일 시 완전히 제거되어 JavaScript 출력을 생성하지 않습니다. 이는 큰 모듈에서 타입을 가져올 때 해당 모듈이 번들에 포함되지 않도록 보장합니다. 인라인 구문도 사용 가능합니다: import { type Config, createApp } from "./app"으로 하나의 문장에서 타입과 값 임포트를 혼합할 수 있습니다. 트리 셰이킹을 사용하는 번들러에서 특히 중요합니다.
tsconfig strict 모드에서 어떤 옵션을 활성화해야 하나요?
"strict": true를 활성화하면 strictNullChecks(null과 undefined를 명시적으로 처리해야 함), noImplicitAny(모든 변수에 명시적이거나 추론 가능한 타입 필요), strictFunctionTypes(함수 매개변수 타입이 반변적으로 검사됨), strictPropertyInitialization(클래스 속성 초기화 필수)을 포함한 모든 엄격한 검사가 한 번에 활성화됩니다. 이 옵션들은 컴파일 시점에 가장 흔한 TypeScript 오류를 잡아주며 모든 새 프로젝트에 권장됩니다.