이 글은 제가 타입챌린지를 하면서 해석한 내용을 적는 글입니다. 틀린 내용이 있으면 댓글 달아주시면 감사하겠습니다.
문자열을 제네릭 인자로 받고, 해당 문자열의 맨 앞 글자를 대문자로 리턴하는 타입이다.
가장 간단한 방법은 이거다.
type MyCapitalize<S extends string> = Capitalize<S>;
근데 이런식으로 답을 쓰는 사람은 없겠지...
그래서 일단 노가다를 해보았다.
아래는 내가 작성한 답이다.
type Upper = {
a: "A", b: "B", c: "C", d: "D", e: "E", f: "F", g: "G",
h: "H", i: "I", j: "J", k: "K", l: "L", m: "M",
n: "N", o: "O", p: "P", q: "Q", r: "R", s: "S", t: "T",
u: "U", v: "V", w: "W", x: "X", y: "Y", z: "Z"
}
type MyCapitalize<S extends string> = S extends `${infer F}${infer R}` ?
(F extends keyof Upper ?
`${Upper[F]}${R}` :
`${F}${R}`) :
S;
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<MyCapitalize<'foobar'>, 'Foobar'>>,
Expect<Equal<MyCapitalize<'FOOBAR'>, 'FOOBAR'>>,
Expect<Equal<MyCapitalize<'foo bar'>, 'Foo bar'>>,
Expect<Equal<MyCapitalize<''>, ''>>,
Expect<Equal<MyCapitalize<'a'>, 'A'>>,
Expect<Equal<MyCapitalize<'b'>, 'B'>>,
Expect<Equal<MyCapitalize<'c'>, 'C'>>,
Expect<Equal<MyCapitalize<'d'>, 'D'>>,
Expect<Equal<MyCapitalize<'e'>, 'E'>>,
Expect<Equal<MyCapitalize<'f'>, 'F'>>,
Expect<Equal<MyCapitalize<'g'>, 'G'>>,
Expect<Equal<MyCapitalize<'h'>, 'H'>>,
Expect<Equal<MyCapitalize<'i'>, 'I'>>,
Expect<Equal<MyCapitalize<'j'>, 'J'>>,
Expect<Equal<MyCapitalize<'k'>, 'K'>>,
Expect<Equal<MyCapitalize<'l'>, 'L'>>,
Expect<Equal<MyCapitalize<'m'>, 'M'>>,
Expect<Equal<MyCapitalize<'n'>, 'N'>>,
Expect<Equal<MyCapitalize<'o'>, 'O'>>,
Expect<Equal<MyCapitalize<'p'>, 'P'>>,
Expect<Equal<MyCapitalize<'q'>, 'Q'>>,
Expect<Equal<MyCapitalize<'r'>, 'R'>>,
Expect<Equal<MyCapitalize<'s'>, 'S'>>,
Expect<Equal<MyCapitalize<'t'>, 'T'>>,
Expect<Equal<MyCapitalize<'u'>, 'U'>>,
Expect<Equal<MyCapitalize<'v'>, 'V'>>,
Expect<Equal<MyCapitalize<'w'>, 'W'>>,
Expect<Equal<MyCapitalize<'x'>, 'X'>>,
Expect<Equal<MyCapitalize<'y'>, 'Y'>>,
Expect<Equal<MyCapitalize<'z'>, 'Z'>>,
]
일단 Upper라는 타입을 만들어서 Upper타입에 소문자가 들어오면, 그에 대응되는 대문자를 리턴하도록 만들어준다.
type MyCapitalize<S extends string> : string타입인 S를 제네릭 인자로 받는 MyCapitalize 타입을 정의한다.
S extends `${infer F}${infer R}` ? : 여기서 infer F와 infer R을 하면, 앞에 있는 infer F는 길이가 1인 문자를 지칭하는 것 같다. 해보니까 되더라. 그래서 해석을 하면, S가 F와 R로 나뉜다면 이라는 뜻이다.
(`${Upper[F]}${R}` : `${F}${R}`) : Upper에서 F에 해당하는 타입(대문자)를 꺼내서 나머지 문자열 R과 같이 출력하고 아니라면 원래 문장 그대로 출력한다. (FOOBAR의 예제 때문에 ${F}${R}이 필요하다)
S; : 그리고 S가 F와 R로 나뉘어지지 않는다면 S를 그대로 출력한다. (S가 아니라 "" 여도 상관없다)
그리고... UpperCase라는 타입이 있다는걸 조금 늦게 알았는데, 이를 활용한 답은 이러하다.
type MyCapitalize<S extends string> = S extends `${infer F}${infer R}` ?
`${Uppercase<F>}${R}` : S;
S가 F과 R로 나누어진다면.. F를 UpperCase해서 R과 붙여서 출력하고, 아니면 S를 그대로 출력한다는 뜻이다.
'Language > Typescript' 카테고리의 다른 글
타입챌린지 : 119-ReplaceAll (medium) (0) | 2023.03.31 |
---|---|
타입챌린지 : 116-Replace (medium) (0) | 2023.03.30 |
타입챌린지 : 108-Trim (medium) (0) | 2023.03.28 |
타입챌린지 : 106-Trim Left (medium) (0) | 2023.03.27 |
타입챌린지 : 62-Type Lookup (0) | 2023.03.24 |