FEInterview Prep

typescript · high priority

TypeScript 타입 시스템 심화

제네릭, 조건부 타입, Mapped Types 완전 정복

advanced 난이도4시간토스카카오네이버당근
시작 전
이해도
매우 낮음

학습 개요

탄생 배경

쉬운 설명

복잡한 개념을 실생활 비유로 설명합니다.

레고 블록 호환성

TypeScript의 구조적 타이핑은 레고 블록처럼 연결 부분의 모양이 같으면 맞는 것으로 인정합니다. 제네릭은 "어떤 색 블록이든 넣을 수 있는 틀"로, 실제 색이 정해질 때 구체적인 타입이 됩니다. 조건부 타입은 "블록 색에 따라 다른 모양을 내뱉는 기계"입니다.

핵심 개념

구조적 타이핑 동작typescript
1interface Point2D { x: number; y: number; }
2interface Point3D { x: number; y: number; z: number; }
3
4// ✅ Point3D는 Point2D의 모든 프로퍼티를 가지므로 호환됨
5function printPoint(p: Point2D) { console.log(p.x, p.y); }
6
7const point3D: Point3D = { x: 1, y: 2, z: 3 };
8printPoint(point3D); // OK — 구조적으로 호환
9
10// 브랜딩으로 Nominal Typing 흉내 내기
11type UserId = string & { readonly _brand: 'UserId' };
12type OrderId = string & { readonly _brand: 'OrderId' };
13function getUser(id: UserId) { /* ... */ }
14const orderId = 'order-123' as OrderId;
15// getUser(orderId); // ❌ Error — 구조가 달라 호환 안 됨

실무 적용

어떤 상황에서 사용하는가

공통 API 클라이언트와 폼 유틸리티 타입 설계

어떻게 적용하는가

제네릭으로 API 클라이언트 함수 타입 안전하게 → infer로 응답 타입 자동 추출 → Mapped Types로 폼 validation 타입 파생 → Discriminated Union으로 API 응답 상태 관리

흔한 실수와 안티패턴

  • any 사용은 타입 오류를 숨깁니다. unknown으로 받고 타입 가드로 좁히세요
  • 타입 단언(as)은 컴파일러를 속이는 것 — 런타임 오류를 유발할 수 있음
  • 너무 복잡한 조건부 타입은 컴파일 성능 저하 유발 — 단순하게 유지

면접 질문

심화토스카카오네이버

답변 방향 힌트

구조적 타이핑은 타입 이름이 아닌 구조가 호환되면 할당 가능. Discriminated Union은 공통 리터럴 필드로 타입을 분기합니다.

반드시 언급할 키워드

  • 구조적 타이핑: 이름이 달라도 구조가 같으면 호환
  • Java/C#은 명목적(Nominal) 타이핑 — 이름 기반
  • Discriminated Union: 공통 리터럴 필드(태그)로 타입 분기
  • switch/if로 태그 필드 체크 → 각 브랜치에서 타입 자동 좁혀짐

예상 꼬리 질문

  • unknown과 any의 차이는 무엇인가요?
  • ReturnType, Parameters 같은 내장 유틸리티 타입은 내부적으로 어떻게 구현되나요?

학습 자료