IT일상

타입스크립트 템플릿 리터럴 타입 본문

프론트엔드

타입스크립트 템플릿 리터럴 타입

solo5star 2023. 3. 27. 15:23
리뉴얼 된 블로그로 보기: https://solo5star.dev/posts/31/

 

type Category = '한식' | '중식' | '일식' | '기타';

function printCategory(category: Category) {
  // '한식', '중식', '일식', '기타' 중 하나
}

printCategory('한식'); // OK
printCategory('한...식'); // ERROR

 

위와 같이 문자열을 강제하는 String Literal Type을 사용하는 것은 자주 보셨을 겁니다.

 

타입스크립트의 기능 중 하나인 Template Literal Type을 사용하면 더 다양한 String Literal Type을 만들 수 있습니다.

 

 

기본적인 사용법

type HttpMethods = 'GET' | 'OPTION' | 'HEAD';

type HttpUrlPaths = '/animals' | '/fruits';

type HttpEndpoints = `${HttpMethods} ${HttpUrlPaths}`;
// 'GET /animals' | 'OPTION /animals' | 'HEAD /animals' | 'GET /fruits' | 'OPTION /fruits' | 'HEAD /fruits'

먼저, Back quote (`)를 사용하여 문자열을 나타냅니다. 그리고 ${} 를 사용하여 String Literal Type을 넣습니다. 템플릿에 삽입된 기존의 String Literal Type으로 새로운 String Literal Type이 만들어집니다.

 

 

예시: Union Type을 사용하여 만들기

type Events = 'click' | 'hover' | 'keyup' | 'keydown';

type EventHandlers = `on${Events}`;
// 'onclick' | 'onhover' | 'onkeyup' | 'onkeydown';

Events 라는 타입에서 on이라는 단어를 붙여 'onclick' | 'onhover' | 'onkeyup' | 'onkeydown' 라는 새로운 Union Type을 만들 수 있습니다.

 

 

예시: Primitive Type을 사용하여 만들기

type HttpEndpoints =
  | `GET /animals/popular`
  | `GET /animals/${number}`
  | `GET /animals/search/${string}`;

number, string 타입을 넣을 수도 있습니다.

 

아쉽게도 number, string은 포괄적인 타입이므로 VSCode에서 자동완성으로 표시되지는 않습니다.

 

타입 자체는 의도한 대로 잘 작동하므로 참고하시면 될 것 같습니다.

 

참고로, boolean은 true | false로 잘 동작합니다.

 

 

예시: Conditional Type에서 사용하기

(Tistory의 TypeScript 코드블럭이 깨져서 VSCode 스크린샷으로 대체합니다.)

 

extends를 사용한 Conditional Type에서도 사용할 수 있습니다.

 

위의 예시에서는 인자로 주어진 selector 라는 문자열이 맨 끝에 ?가 붙어있는지 검사합니다. 이에 따라 리턴 타입이 결정됩니다.

 

 

예시: infer를 사용하여 String Literal Type 추출하기

type HttpEndpoints =
  | `GET /animals/popular`
  | `GET /animals/${number}`
  | `GET /animals/search/${string}`
  | `POST /animals`
  | `POST /animals/${number}`
  | `PUT /animals/${number}`;

type GetHttpMethods<T> = T extends `${infer U} ${string}` ? U : never;

type HttpMethods = GetHttpMethods<HttpEndpoints>;
// 'GET' | 'POST' | 'PUT'

기존의 String Literal Type에서 원하는 부분만 추출하여 사용할 수도 있습니다. Conditional Type과 함께 infer 키워드를 쓰면 해당 부분만 추출하는 타입을 만들 수 있습니다.

 

 

라이브러리

이러한 타입의 문법들을 응용하여 다양한 편리 기능들을 제공하는 라이브러리들이 많습니다.

 

* https://github.com/tani/jsonup: String Literal Type으로 된 JSON을 파싱한 타입으로 만들어 줍니다.

* https://github.com/g-plane/typed-query-selector: querySelector를 분석하여 적합한 반환 HTMLElement 타입을 만들어 줍니다.

 

 

빌트 인(Built-in) 타입 유틸리티

타입스크립트에 내장되어 있는 유틸리티 타입들입니다. 간단한 것들이기 때문에 설명 없이 입출력만 첨부하였습니다.

Uppercase<StringType>

 

Lowercase<StringType>

 

Capitalize<StringType>

 

Uncapitalize<StringType>

 

 

맺음말

기존에는 String Literal Type을 일일이 하드코딩하여 타입을 정의해주어야 했습니다. 하지만 Template Literal Type을 사용하면 더 강력한 타입들을 만들 수 있을 겁니다! 특히 Conditional Type과 잘 연계해서 쓴다면 정말 멋진 타입을 만들어 나갈 수 있지 않을까 싶습니다.

 

 

참고자료

* https://toss.tech/article/template-literal-types

* https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html

Comments