TypeScript 28강: 고급 타입 추론 및 타입 호환성 이해하기
타입스크립트의 타입 추론(Type Inference)이란?
타입스크립트(TypeScript)의 타입 추론은 명시적으로 타입을 지정하지 않아도, 코드의 문맥을 분석하여 타입을 자동으로 결정하는 기능입니다. 이로 인해 코드가 간결해지고, 생산성이 향상됩니다.
let name = "TypeScript"; // string으로 추론 let count = 10; // number로 추론
명시적으로 : string
또는 : number
와 같이 선언하지 않아도, 변수에 할당된 값을 기준으로 타입이 결정됩니다.
타입 추론의 주요 전략
타입스크립트는 다양한 전략을 통해 타입을 추론합니다.
- 초기화 추론 (Initialization Inference): 변수 선언 시 초기값을 통해 추론
- 기본값 추론 (Default Parameter Inference): 함수의 기본값을 기준으로 추론
- 컨텍스트 기반 추론 (Contextual Typing): 이벤트 핸들러 등에서 문맥 기반 추론
window.addEventListener("click", (e) => { console.log(e.clientX); // e는 MouseEvent로 추론됨 });
이러한 추론 기능은 코드 작성 시 IDE의 자동 완성과 타입 검사의 정확도를 높여줍니다.
타입 넓히기(Widening)와 좁히기(Narrowing)
타입스크립트는 값을 기반으로 타입을 더 구체화하거나 일반화할 수 있습니다.
- 넓히기 (Widening):
const
가 아닌let
으로 선언 시, 타입이 일반적인 형태로 추론됨 - 좁히기 (Narrowing): 조건문 등을 통해 타입을 구체적으로 좁힐 수 있음
let status = "success"; // string으로 넓혀짐 const fixed = "success"; // "success" 리터럴 타입으로 좁혀짐
변수를 리터럴 타입으로 고정하고 싶다면 const
나 as const
를 사용합니다.
타입 호환성(Type Compatibility)이란?
타입 호환성은 하나의 타입을 다른 타입에 할당할 수 있는지 여부를 결정하는 기준입니다. TypeScript는 구조적 타입 시스템을 기반으로 하며, 두 타입의 구조가 일치하면 호환된다고 판단합니다.
interface Animal { name: string; } interface Dog { name: string; breed: string; } let animal: Animal; let dog: Dog = { name: "Buddy", breed: "Golden Retriever" }; animal = dog; // OK: Dog는 Animal의 구조를 포함함
반대로, animal
을 dog
에 할당하면 오류가 발생합니다. 누락된 속성이 있기 때문입니다.
함수의 타입 호환성
함수는 매개변수의 수와 타입, 반환 타입에 따라 호환성이 결정됩니다.
type FuncA = (a: number) => void; type FuncB = (a: number, b: number) => void; let fa: FuncA = (x) => {}; let fb: FuncB = (x, y) => {}; fa = fb; // OK // fb = fa; // Error: 두 번째 매개변수 누락
TypeScript는 매개변수가 더 적은 쪽은 더 많은 쪽에 할당 가능하다고 판단합니다.
타입 호환성에서의 특별 규칙
- void 반환 함수는 다른 반환값이 있어도 할당 가능
- 제네릭 타입은 구조가 같으면 호환 가능
- readonly 속성이나
private
필드는 호환성에 영향을 줌
type ReadA = { readonly name: string }; type MutB = { name: string }; // let a: ReadA = { name: "TS" }; // let b: MutB = a; // Error: readonly 무시 불가
타입 호환성 판단 기준 요약
타입스크립트의 호환성은 다음과 같은 기준을 따릅니다.
- 모든 필드가 포함되어야 한다
- 매개변수 수는 적은 쪽이 많은 쪽에 할당 가능
- 기본적으로 구조적 타이핑을 따른다
strict 모드와 타입 추론
tsconfig.json
에서 "strict": true
를 설정하면 타입 검사가 더 엄격해집니다. 암시적 any 금지, null 검사 강화 등으로 타입 추론이 정밀해지고, 코드의 안전성이 높아집니다.
{ "compilerOptions": { "strict": true, "noImplicitAny": true, "strictNullChecks": true } }
실무에서는 strict 모드를 사용하는 것이 권장됩니다.
실전 예제: 조건부 타입에서의 추론
타입스크립트는 조건부 타입에서도 추론 기능을 제공합니다.
type GetReturnType= T extends (...args: any[]) => infer R ? R : never; type Result = GetReturnType<() => string>; // string
infer
키워드는 조건부 타입에서 특정 타입을 추론할 수 있게 해주며, 복잡한 타입 변형 작업에 유용합니다.
결론: 타입 추론과 호환성은 타입스크립트의 핵심
타입 추론은 타입스크립트의 편의성과 강력함을 동시에 제공하며, 타입 호환성은 타입 간의 관계를 명확하게 정의합니다. 이 두 개념을 이해하고 활용하면, 복잡한 타입 시스템에서도 안정적이고 유연한 코드를 작성할 수 있습니다.
실무에서의 안전한 코드 작성을 위해서는 타입 추론 결과를 이해하고, 필요한 경우 명시적으로 타입을 지정하는 습관이 중요합니다. 또한 strict 모드를 활용해 가능한 오류를 사전에 방지하는 것이 바람직합니다.