템플릿 리터럴은 백틱 기호를 사용하며 String Literal Type을 기반으로 다른 타입을 만들거나 String을 표현하는 문법입니다.
문자열 사이에 변수를 추가하려먼 +
기호를 통해 템플릿 로직을 구현해야 하지만 템플릿 리터럴은 하나의 문자열로 간편하게 구현 가능합니다.
Typescript에는 문자열, 숫자, boolean 세 가지 리터럴 타입이 있으며 union type, type guard 등 타입을 정의하는데 있어 enum
과 유사한 기능을 제공합니다.
리터럴 타입으로 정의된 타입을 사용할 경우 허용된 값을 사용하지 않으면 오류가 발생하게 됩니다.
type Market = 'opensea' | 'blur' | 'pala';
// market 값으로는 'opensea', 'blur', 'pala'만 사용할 수 있습니다.
function selectMarket(market: Market) {
...
}
type DiceNumber: 1 | 2 | 3 | 4 | 5 | 6;
// rollDice 함수의 return 값으로 1,2,3,4,5,6 중 하나가 나온다는 것을 예상할 수 있습니다.
function rollDice(): DiceNumber {
return (Math.floor(Math.random() * 6) + 1) as DiceNumber;
}
아래 예시는 isSuccess의 값이 true
일 경우 data의 값은 object
타입이 올 수 있고 false
일 경우 data
는 어떠한 타입의 값도 올 수 없도록 만든 예시입니다.
type ResultSuccess {
isSuccess: true;
data: object;
}
type ResultFailure {
isSuccess: false;
data: never;
}
type Result = ResultSuccess | ResultFailure;
다음과 같이 TopBottom, LeftRight를 조합하여 Align에 대한 하나의 타입을 만드는것 처럼 ${}
를 사용해 중간에 다른 타입을 혼합하여 템플릿 리터럴을 만들 수 있습니다.
type TopBottom = 'top' | 'middle' | 'bottom'
type LeftRight = 'left' | 'center' | 'right'
type Align = `${TopBottom}-${leftRight}`;
/* 'top-left' , 'top-cetner' , 'top-right'
'middle-left', 'middle-cetner', 'middle-right'
'bottom-left', 'bottom-cetner', 'bottom-right' */
기존
문자열 개행을 하려면 이스케이프 문자\
를 사용하여 개행할 위치를 지정하고 다음 줄 처음에 \n
을 넣어 구현합니다.
멀티라인 리터럴
엔터를 인식하여 개행을 처리합니다.
/*
Never gonna give you up
Never gonna let you down
*/
let hard = 'Never gonna give you up \
\nNever gonna let you down';
let easy = `Never gonna give you up
Never gonna let you down` ;
기존
문자열 중간에 다른 문자를 삽입할 때 기존에는 +
를 사용하여 구현합니다.
템플릿 리터럴
${}
를 사용하여 중간에 문자를 삽입합니다.
let something = 'pen';
// I have a pen!!
let hard = 'I have a ' + pen + '!!'
let easy = `I have a ${pen}!!`
styled-components를 사용해 봤다면 익숙한 형태로, 함수를 사용할 때 함수명 뒤에 백틱 기호를 사용합니다.
Tagged Templates을 사용하면 문자열을 구성하는 단계에서 중간에 삽입하는 값에 따라 조건을 작성할 수 있습니다.
type Characters = 'Snow White' | 'The Queen';
function magicMirror(texts: TemplateStringsArray, ...characters: [Characters, Characters]) {
let answer: string = 'No!!!';
if (characters[0] === 'Snow White' && characters[0] === characters[1]) {
answer = `Both ${characters[0]} and ${characters[1]} are pretty`;
}
else if (characters[0] === 'The Queen' && characters[0] === characters[1]) {
answer = `Both ${characters[0]} and ${characters[1]} are ugly.`;
}
else if (characters[0] === 'Snow White' && characters[1] === 'The Queen') {
answer = `${characters[0]} is more beautiful than ${characters[1]}.`;
}
return `Q: ${texts.join(' ')}
A: ${answer}`;
}
const tautologyA = magicMirror`Mirror, mirror on the wall ! Is ${'Snow White'} prettier than the ${'The Queen'}?`;
/*
Q: Mirror, mirror on the wall ! Is Snow White prettier than the The Queen
A: Snow White is more beautiful than The Queen.
*/
const tautologyB = magicMirror`Mirror, mirror on the wall ! Is ${'The Queen'} prettier than the ${'Snow White'}?`;
/*
Q: Mirror, mirror on the wall ! Is The Queen prettier than the Snow White
A: No!!!
*/
위의 예시를 보면 Tagged Templates의 사용법은 다음과 같습니다.
function 함수명(texts: TemplateStringsArray, ...values: string[]) {
return `${values[0]} ${texts[0]} ${values[1]}${texts[1]}`
}
const result = 함수명`${'a'} is ${'b'}.`;
// a is b
// texts = ['is', '.'];
// values = ['a', 'b']
첫 번째 파라미터 texts
에는 ${}
로 문자열을 split 한 결과가 들어있으며 두 번째 파라미터 values
에넌 ${}
안의 값이 들어가게 됩니다.
이때, typescript에서는 values
의 타입에 tuple을 적용해 개수를 제한할 수 있으며 타입 또한 명시하여 올 수 있는 타입을 제한할 수 있습니다.
type something = 'a' | 'b';
function 함수명(texts: TemplateStringsArray, ...values: [something, something]) {
return `${values[0]} ${texts[0]} ${values[1]}${texts[1]}`
// return `a is b.`
}
const result = 함수명`${'a'} is ${'b'}.`;
// ${}를 두 번 까지만 사용할 수 있으며 값으로는 something에 해당하는 값만 올 수 있습니다.
좋은 글 감사합니다.