TypeScript 실전 과제 - 템플릿 리터럴 타입(Template Literal Type)

호수·2026년 5월 12일

TypeScript 실전 과제

목록 보기
4/4
post-thumbnail

1. 템플릿 리터럴 타입

JavaScript의 템플릿 리터럴(` )을 타입 레벨에서 사용하는 기능입니다.
문자열 유니언 타입을 조합하거나, 특정 형식의 문자열만 허용하는 타입을 만들 때 유용합니다.

type Direction = "top" | "bottom" | "left" | "right";
type CSSProperty = `margin-${Direction}`;
// "margin-top" | "margin-bottom" | "margin-left" | "margin-right"
패턴설명
`prefix-${T}`T의 각 멤버 앞에 문자열을 붙인 타입
`${T}-suffix`T의 각 멤버 뒤에 문자열을 붙인 타입
`${T}-${U}`T × U의 모든 조합으로 이루어진 타입
Uppercase<T> / Lowercase<T>문자열 타입을 대·소문자로 변환
Capitalize<T> / Uncapitalize<T>첫 글자만 대·소문자로 변환

2. 시나리오

이벤트 시스템 설계하기
아래 Post 타입과 이벤트 이름 규칙을 기반으로, 4가지 상황에 맞는 타입을 템플릿 리터럴 타입으로 만들어보세요.

type Post = {
  id: number;
  title: string;
  content: string;
  authorId: number;
  published: boolean;
  createdAt: Date;
};

type Action = "create" | "update" | "delete" | "publish";

이벤트 이름 규칙은 on + 리소스명(대문자 시작) + 액션명(대문자 시작)입니다.
예: "onPostCreate", "onPostUpdate"


3. 실전 과제

문제 1 — 이벤트 이름 유니언 타입

Action을 기반으로 "onPostCreate" | "onPostUpdate" | "onPostDelete" | "onPostPublish" 형태의 이벤트 이름 유니언 타입을 정의하십시오.
문제 풀어보기 =>

type PostEventName = ?

문제 2 — 이벤트 핸들러 맵 타입

각 이벤트 이름을 키로, () => void 핸들러를 값으로 갖는 객체 타입을 정의하십시오.
문제 풀어보기 =>

// 예시
const handlers: PostEventHandlerMap = {
  onPostCreate: () => console.log("created"),
  onPostUpdate: () => console.log("updated"),
  onPostDelete: () => console.log("deleted"),
  onPostPublish: () => console.log("published"),
};

type PostEventHandlerMap = ?

문제 3 — Post 필드별 getter 함수 타입

Post의 각 키를 기반으로 getTitle, getContent 같은 형태의 getter 이름 유니언 타입을 정의하십시오.
문제 풀어보기 =>

type PostGetter = ?
// "getId" | "getTitle" | "getContent" | "getAuthorId" | "getPublished" | "getCreatedAt"

문제 4 — CSS 유틸리티 클래스 타입

spacing 값(4 | 8 | 16)과 방향(top | bottom | left | right)을 조합한
"p-top-4", "m-bottom-8" 같은 형태의 CSS 유틸리티 클래스 타입을 정의하십시오.
문제 풀어보기 =>

type SpacingValue = 4 | 8 | 16;
type Side = "top" | "bottom" | "left" | "right";

type SpacingClass = ?
// "p-top-4" | "p-top-8" | ... | "m-bottom-16" | ...

4. 풀이 코드

문제 1 — 이벤트 이름 유니언 타입

type PostEventName = `onPost${Capitalize<Action>}`;

// 결과
type PostEventName =
  | "onPostCreate"
  | "onPostUpdate"
  | "onPostDelete"
  | "onPostPublish";

Capitalize"create""Create" 로 변환한 뒤 앞에 "onPost"를 붙입니다.
유니언 타입을 넣으면 각 멤버에 자동으로 적용되어 모든 조합이 만들어집니다.


문제 2 — 이벤트 핸들러 맵 타입

type PostEventHandlerMap = {
  [K in PostEventName]: () => void;
};

// 결과
type PostEventHandlerMap = {
  onPostCreate: () => void;
  onPostUpdate: () => void;
  onPostDelete: () => void;
  onPostPublish: () => void;
};

Mapped Type과 함께 쓰면 유니언 타입의 각 멤버를 키로 갖는 객체 타입을 만들 수 있습니다.


문제 3 — Post 필드별 getter 함수 타입

type PostGetter = `get${Capitalize<string & keyof Post>}`;

// 결과
type PostGetter =
  | "getId"
  | "getTitle"
  | "getContent"
  | "getAuthorId"
  | "getPublished"
  | "getCreatedAt";

keyof Poststring | number | symbol 을 반환할 수 있으므로,
string & 로 교차해 문자열 키만 걸러낸 뒤 Capitalize를 적용합니다.


문제 4 — CSS 유틸리티 클래스 타입

type SpacingClass = `${"p" | "m"}-${Side}-${SpacingValue}`;

// 결과 (일부)
type SpacingClass =
  | "p-top-4"
  | "p-top-8"
  | "p-top-16"
  | "p-bottom-4"
  // ...
  | "m-right-16";

세 개의 유니언(2 × 4 × 3)을 조합하면 TypeScript가 가능한 모든 경우의 수(24가지)를 자동으로 계산합니다.


5. 간단 요약

  • 템플릿 리터럴 타입은 문자열 유니언을 자동으로 조합해 준다
  • Capitalize / Uppercase 등의 내장 문자열 유틸리티와 함께 쓰면 강력하다
  • Mapped Type과 조합하면 키 이름까지 타입으로 강제할 수 있다
  • keyof와 함께 쓸 때는 string & 교차로 문자열 키만 필터링하는 것을 잊지 말자

문자열 규칙이 있는 곳이라면 어디든 — 이벤트 이름, API 경로, CSS 클래스, i18n 키 —
템플릿 리터럴 타입으로 오타를 컴파일 타임에 잡을 수 있습니다.

profile
인포테인먼트에서 동작하는 웹 어플리케이션을 개발합니다.

0개의 댓글