SHIN STORYSHIN STORY
홈포스트C#TypeScriptNext.jsNode.js시리즈
</>SHIN STORY

sdf

탐색

  • 홈
  • 모든 포스트
  • 시리즈
  • 검색

카테고리

  • C#
  • TypeScript
  • Next.js
  • Node.js
  • 알고리즘
  • 개발 도구

© 2025 Shin Blog. All rights reserved.

GitHubRSS
목록으로
TypeScript#TypeScript

TypeScript 팁 #7 — 템플릿 리터럴 타입으로 문자열 타입 조작

SHIN

2025년 4월 27일2분 읽기0
📚

TypeScript 실전 팁 10선

10편
  1. 5TypeScript 팁 #5 — 타입 가드로 런타임 타입 좁히기
  2. 6TypeScript 팁 #6 — 매핑 타입으로 타입 변환하기
  3. 10TypeScript 팁 #1 — strict 모드를 반드시 켜야 하는 이유
  4. 10TypeScript 팁 #2 — 유틸리티 타입 완전 정복
  5. 10TypeScript 팁 #3 — 판별 유니온으로 타입 안전한 상태 관리
  6. 10TypeScript 팁 #4 — 제네릭 제약 조건과 infer 활용
  7. TypeScript 팁 #7 — 템플릿 리터럴 타입으로 문자열 타입 조작현재
  8. 10TypeScript 팁 #8 — 선언 병합과 모듈 보강으로 타입 확장하기
  9. 10TypeScript 팁 #9 — 타입 안전한 에러 처리 패턴
  10. 10TypeScript 팁 #10 — 타입 성능 최적화와 실무 패턴

TypeScript 팁 #7 — 템플릿 리터럴 타입으로 문자열 타입 조작

TypeScript 4.1에서 도입된 템플릿 리터럴 타입은 문자열 패턴을 타입 수준에서 표현할 수 있게 해줍니다.

기본 문법

CODE
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'

CSS 프로퍼티 타입 안전 처리

CODE
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')  // ❌ 잘못된 단위

내장 문자열 조작 타입

CODE
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>

API 경로 타입 안전 처리

CODE
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'   — 잘못된 메서드

이벤트 리스너 타입 자동완성

CODE
type EventName = 'click' | 'focus' | 'blur' | 'change'
type EventHandler = `on${Capitalize<EventName>}`
// 'onClick' | 'onFocus' | 'onBlur' | 'onChange'

interface ComponentProps {
  [K in EventHandler]?: (e: Event) => void
}

경로 파라미터 추출

CODE
// '/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' })

i18n 번역 키 타입 안전 처리

CODE
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')  // ❌ 존재하지 않는 키

템플릿 리터럴 타입은 런타임 유효성 검사 없이도 문자열 패턴을 컴파일 타임에 검증할 수 있게 해줍니다.

공유
S

SHIN

.NET 개발자입니다

GitHub

이전 포스트

TypeScript 팁 #6 — 매핑 타입으로 타입 변환하기

다음 포스트

TypeScript 팁 #8 — 선언 병합과 모듈 보강으로 타입 확장하기

TypeScript 팁 #8 — 선언 병합과 모듈 보강으로 타입 확장하기

같은 카테고리 포스트

TypeScript 팁 #10 — 타입 성능 최적화와 실무 패턴

TypeScript 팁 #10 — 타입 성능 최적화와 실무 패턴

2025년 5월 3일· 3분
TypeScript 팁 #9 — 타입 안전한 에러 처리 패턴

TypeScript 팁 #9 — 타입 안전한 에러 처리 패턴

2025년 5월 1일· 2분
TypeScript 팁 #8 — 선언 병합과 모듈 보강으로 타입 확장하기

TypeScript 팁 #8 — 선언 병합과 모듈 보강으로 타입 확장하기

2025년 4월 29일· 2분

댓글