SHIN
TypeScript 실전 팁 10선
10편TypeScript 4.1에서 도입된 템플릿 리터럴 타입은 문자열 패턴을 타입 수준에서 표현할 수 있게 해줍니다.
type Greeting = `Hello, ${string}`
const a: Greeting = 'Hello, World' // ✅
const b: Greeting = 'Hello, TypeScript' // ✅
const c: Greeting = 'Hi, World' // ❌ 'Hello,'로 시작해야 함
// 유니온과 조합
type Direction = 'top' | 'bottom' | 'left' | 'right'
type MarginProp = `margin-${Direction}`
// 'margin-top' | 'margin-bottom' | 'margin-left' | 'margin-right'type CSSUnit = 'px' | 'rem' | 'em' | '%' | 'vh' | 'vw'
type CSSValue = `${number}${CSSUnit}`
function setWidth(value: CSSValue) {
document.body.style.width = value
}
setWidth('100px') // ✅
setWidth('1.5rem') // ✅
setWidth('100') // ❌ 단위 없음
setWidth('100xyz') // ❌ 잘못된 단위type Upper = Uppercase<'hello'> // 'HELLO'
type Lower = Lowercase<'HELLO'> // 'hello'
type Cap = Capitalize<'hello'> // 'Hello'
type Uncap = Uncapitalize<'Hello'> // 'hello'
// 실전: camelCase → SCREAMING_SNAKE_CASE
type ScreamingSnake<S extends string> =
Uppercase<S extends `${infer Head}${infer Tail}`
? Tail extends Uncapitalize<Tail>
? `${Head}${ScreamingSnake<Tail>}`
: `${Head}_${ScreamingSnake<Tail>}`
: S>type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
type ApiPath = `/api/${string}`
type Endpoint = `${HttpMethod} ${ApiPath}`
const endpoints: Endpoint[] = [
'GET /api/users',
'POST /api/users',
'DELETE /api/users/123',
]
// ❌ 컴파일 오류
// 'GET /users' — /api/ 접두사 없음
// 'FETCH /api/users' — 잘못된 메서드type EventName = 'click' | 'focus' | 'blur' | 'change'
type EventHandler = `on${Capitalize<EventName>}`
// 'onClick' | 'onFocus' | 'onBlur' | 'onChange'
interface ComponentProps {
[K in EventHandler]?: (e: Event) => void
}// '/users/:id/posts/:postId'에서 파라미터 추출
type ExtractParams<Path extends string> =
Path extends `${infer _Start}:${infer Param}/${infer Rest}`
? Param | ExtractParams<Rest>
: Path extends `${infer _Start}:${infer Param}`
? Param
: never
type Params = ExtractParams<'/users/:id/posts/:postId'>
// 'id' | 'postId'
function route<Path extends string>(
path: Path,
params: Record<ExtractParams<Path>, string>
) {
// params.id, params.postId 자동완성 ✅
}
route('/users/:id/posts/:postId', { id: '1', postId: '42' })const translations = {
'user.name': '이름',
'user.email': '이메일',
'post.title': '제목',
} as const
type TranslationKey = keyof typeof translations
// 'user.name' | 'user.email' | 'post.title'
function t(key: TranslationKey): string {
return translations[key]
}
t('user.name') // ✅
t('user.phone') // ❌ 존재하지 않는 키템플릿 리터럴 타입은 런타임 유효성 검사 없이도 문자열 패턴을 컴파일 타임에 검증할 수 있게 해줍니다.