개발새발
정교한 문자열 조작을 위해 템플릿 리터럴 타입을 사용하자 본문
템플릿 리터럴 타입의 기본 개념
템플릿 리터럴 타입은 특수한 문자열 타입이다. 자바스크립트의 템플릿 리터럴과 유사하게 백틱(`)과 보간 구문(${})을 사용하지만, 값이 아닌 타입을 구성하기 위해 사용된다.
예를 들어, 다음과 같이 간단한 템플릿 리터럴 타입을 선언할 수 있다.
type Literal = "literal";
type Template = `template ${Literal}`; // Template 타입은 "template literal"과 동일하다.
const str: Template = "template literal";
문자열 타입 안에 다른 타입을 변수처럼 넣을 수 있으며, 이를 통해 정해진 문자열만을 변수에 대입하도록 엄격하게 관리할 수 있다.
문자열 범위를 넓히는 템플릿 리터럴 타입
템플릿 리터럴 타입의 보간 부분에 특정 문자열 대신 string을 사용하면, 보다 유연한 문자열 타입을 만들 수 있다.
type Template = `template ${string}`;
let str: Template = "template ";
str = "template hello";
str = "template 123";
str = "template"; // 에러 발생: "template"은 보간된 문자열이 없으므로 Template 타입에 부합하지 않는다.
위 예제에서 마지막 할당은 템플릿 문자열 뒤에 띄어쓰기가 없기 때문에 타입 에러가 발생한다. 이처럼 템플릿 리터럴 타입은 문자열 변수의 값을 엄격하게 관리할 수 있다.
다양한 문자열 조합을 위한 활용
템플릿 리터럴 타입은 여러 개의 문자열을 조합할 때 매우 편리하다. 예를 들어, 지역과 이동수단을 조합하여 '지역:이동수단' 형식의 문자열 타입을 만들 수 있다. 지역이 seoul, suwon, busan이고, 이동수단이 car, bike, walk인 경우 각각의 조합은 9가지가 된다. 템플릿 리터럴 타입을 사용하면 아래와 같이 선언할 수 있다.
type City = 'seoul' | 'suwon' | 'busan';
type Vehicle = 'car' | 'bike' | 'walk';
type ID = `${City}:${Vehicle}`;
const id: ID = 'seoul:walk'; // 올바른 타입의 값이다.
지역이나 이동수단의 종류가 늘어나더라도 각각의 타입에 추가하면, ID 타입은 알아서 모든 조합을 표현할 수 있다.
제네릭 및 infer와 결합한 템플릿 리터럴 타입
템플릿 리터럴 타입은 제네릭 및 infer와 결합하여 보다 정교한 문자열 조작도 가능하다. 예제로 좌우에 있는 특정 문자를 제거하는 타입을 만들어보자. 여기서는 좌우에 있는 문자 'x'를 제거하는 과정을 재귀 타입으로 구현한다.
type RemoveX<Str> = Str extends `x${infer Rest}`
? RemoveX<Rest>
: Str extends `${infer Rest}x`
? RemoveX<Rest>
: Str;
type Removed = RemoveX<"xxtestxx">; // 결과는 "test"가 된다.
위 코드를 단계별로 살펴보면 다음과 같다.
- RemoveX<"xxtestxx">는 문자열이 'x'로 시작하므로, Rest는 "xtestxx"가 된다.
- RemoveX<"xtestxx"> 역시 'x'로 시작하여 Rest가 "testxx"가 된다.
- RemoveX<"testxx">에서는 좌측에는 'x'가 없으므로, 오른쪽이 'x'로 끝나는 조건을 평가한다. 이때 Rest는 "testx"가 된다.
- RemoveX<"testx">는 다시 오른쪽 조건에 부합하여 Rest가 "test"가 된다.
- RemoveX<"test">는 더 이상 좌측이나 우측에 'x'가 없으므로 그대로 "test"가 최종 결과이다.
이와 같이 템플릿 리터럴 타입과 재귀 타입의 결합을 통해 문자열 양쪽의 특정 문자를 제거하는 정교한 타입 조작이 가능하다.
양쪽 공백 제거 함수
위의 원리를 응용하여 좌우 공백을 제거하는 타입도 만들 수 있다. 공백 대신 다른 문자를 대상으로 동일한 원리로 제거할 수 있으며, 아래는 공백을 제거하는 예제이다.
type RemoveEmpty<Str> = Str extends ` ${infer Rest}`
? RemoveEmpty<Rest>
: Str extends `${infer Rest} `
? RemoveEmpty<Rest>
: Str;
type RemovedSpace = RemoveEmpty<" test ">; // 결과는 "test"가 된다.
이 경우에도 문자열의 좌측과 우측에 있는 공백이 재귀적으로 제거되어 최종적으로 "test" 문자열만 남게 된다.
이처럼 템플릿 리터럴 타입은 정교한 문자열 조작을 위한 강력한 도구이다.
- 정확한 문자열 제어: 특정 패턴의 문자열만 허용하도록 타입을 선언할 수 있다.
- 조합의 간소화: 여러 문자열 조합을 자동으로 생성할 수 있다.
- 제네릭 및 재귀와 결합: 복잡한 문자열 변환 로직을 타입 수준에서 구현할 수 있다.
'Typescript' 카테고리의 다른 글
타입스크립트는 건망증이 심하다 (0) | 2025.04.03 |
---|---|
추가적인 타입 검사에는 satisfies 연산자를 사용하자 (0) | 2025.04.03 |
자기 자신을 타입으로 사용하는 재귀 타입이 있다 (0) | 2025.04.02 |
타입을 좁혀 정확한 타입을 얻어내자 (0) | 2025.04.02 |
infer로 타입스크립트의 추론을 직접 활용하자 (0) | 2025.04.02 |