🌱 ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Type-challenges] 108, 110, 116, 119, 191
    Front-End/TypeScript 2024. 3. 15. 14:12
    🍀 목차
    108 - Trim
    110 - Capitalize
    116 - Replace
    119 - ReplaceAll
    191 - Append Argument

     

    108 - Trim

    // 정확한 문자열 타입이고 양쪽 끝의 공백이 제거된 새 문자열을 반환하는 Trim<T>를 구현하십시오.
    
    // 예시
    type trimmed = Trim<'  Hello World  '> // 기대되는 결과는 'Hello World'입니다.
    /* _____________ 여기에 코드 입력 _____________ */
    
    type Trim<S extends string> = any
    
    /* _____________ 테스트 케이스 _____________ */
    import type { Equal, Expect } from '@type-challenges/utils'
    
    type cases = [
      Expect<Equal<Trim<'str'>, 'str'>>,
      Expect<Equal<Trim<' str'>, 'str'>>,
      Expect<Equal<Trim<'     str'>, 'str'>>,
      Expect<Equal<Trim<'str   '>, 'str'>>,
      Expect<Equal<Trim<'     str     '>, 'str'>>,
      Expect<Equal<Trim<'   \n\t foo bar \t'>, 'foo bar'>>,
      Expect<Equal<Trim<''>, ''>>,
      Expect<Equal<Trim<' \n\t '>, ''>>,
    ]
    type Space = ' ' | '\t' | '\n';
    type Trim<S extends string> = S extends `${Space}${infer T}` | `${infer T}${Space}` ? Trim<T> : S;


    110 - Capitalize

    // 문자열의 첫 글자만 대문자로 바꾸고 나머지는 그대로 놔두는 Capitalize<T>를 구현하세요.
    
    // 예시
    type capitalized = Capitalize<'hello world'> // expected to be 'Hello world'

     

    /* _____________ 여기에 코드 입력 _____________ */
    
    type MyCapitalize<S extends string> = any
    
    /* _____________ 테스트 케이스 _____________ */
    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'>>,
    ]

     

    type MyCapitalize<S extends string> = S extends `${infer head}${infer tail}` ? `${Uppercase<head>}${tail}` : S;

     

    Template Literal Types로 Uppercase<StrintType>을 제공한다. 빌트인 타입을 사용하지 않으려면 객체로 대문자(key)를 소문자(value)로 매치시킬 수도 있다.

     

     

    116 - Replace

    // 문자열 S에서 From를 찾아 한 번만 To로 교체하는 Replace<S, From, To>를 구현하세요.
    
    // 예시
    
    type replaced = Replace<'types are fun!', 'fun', 'awesome'> 
    // expected to be 'types are awesome!'
    /* _____________ 여기에 코드 입력 _____________ */
    
    type Replace<S extends string, From extends string, To extends string> = any
    
    /* _____________ 테스트 케이스 _____________ */
    import type { Equal, Expect } from '@type-challenges/utils'
    
    type cases = [
      Expect<Equal<Replace<'foobar', 'bar', 'foo'>, 'foofoo'>>,
      Expect<Equal<Replace<'foobarbar', 'bar', 'foo'>, 'foofoobar'>>,
      Expect<Equal<Replace<'foobarbar', '', 'foo'>, 'foobarbar'>>,
      Expect<Equal<Replace<'foobarbar', 'bar', ''>, 'foobar'>>,
      Expect<Equal<Replace<'foobarbar', 'bra', 'foo'>, 'foobarbar'>>,
      Expect<Equal<Replace<'', '', ''>, ''>>,
    ]

     

    type Replace<S extends string, From extends string, To extends string> = S extends `${infer Left}${From}${infer Right}` ? `${Left}${To}${Right}` : S;

     

     From이 공백일 때를 처리해주지 않으면 Replace<'foobarbar', '', 'foo'>의 결과가 'foobarbar'가 아닌 'ffoooobarbar'가 된다. 

    From이 공백일 때는 never이 반환되게 해준다.

     

    type Replace<S extends string, From extends string, To extends string> = S extends `${infer Left}${From extends '' ? never: From}${infer Right}` ? `${Left}${To}${Right}` : S;

     

     

    119 - ReplaceAll

    // 주어진 문자열 S에서 부분 문자열 From을 찾아 모두 To로 교체하는 \
    // 제네릭 ReplaceAll<S, From, To>을 구현하세요.
    
    // 예시
    type replaced = ReplaceAll<'t y p e s', ' ', ''> // expected to be 'types'
    /* _____________ 여기에 코드 입력 _____________ */
    
    type ReplaceAll<S extends string, From extends string, To extends string> = any
    
    /* _____________ 테스트 케이스 _____________ */
    import type { Equal, Expect } from '@type-challenges/utils'
    
    type cases = [
      Expect<Equal<ReplaceAll<'foobar', 'bar', 'foo'>, 'foofoo'>>,
      Expect<Equal<ReplaceAll<'foobar', 'bag', 'foo'>, 'foobar'>>,
      Expect<Equal<ReplaceAll<'foobarbar', 'bar', 'foo'>, 'foofoofoo'>>,
      Expect<Equal<ReplaceAll<'t y p e s', ' ', ''>, 'types'>>,
      Expect<Equal<ReplaceAll<'foobarbar', '', 'foo'>, 'foobarbar'>>,
      Expect<Equal<ReplaceAll<'barfoo', 'bar', 'foo'>, 'foofoo'>>,
      Expect<Equal<ReplaceAll<'foobarfoobar', 'ob', 'b'>, 'fobarfobar'>>,
      Expect<Equal<ReplaceAll<'foboorfoboar', 'bo', 'b'>, 'foborfobar'>>,
      Expect<Equal<ReplaceAll<'', '', ''>, ''>>,
    ]

     

    type ReplaceAll<S extends string, From extends string, To extends string> = 
    From extends '' ? 
    S : S extends `${infer Left}${From}${infer Right}` ? 
    `${ReplaceAll<Left, From, To>}${To}${ReplaceAll<Right,From,To>}` : S;


    191 - Append Argument

    // 함수 타입 Fn과 어떤 타입 A가 주어질 때 
    // Fn의 인수와 A를 마지막 인수로 받는 Fn과 동일한 함수 유형인 G를 생성하세요.
    
    // 예시
    type Fn = (a: number, b: string) => number
    
    type Result = AppendArgument<Fn, boolean> 
    // 기대되는 결과는 (a: number, b: string, x: boolean) => number 입니다.
    /* _____________ 여기에 코드 입력 _____________ */
    
    type AppendArgument<Fn, A> = any
    
    /* _____________ 테스트 케이스 _____________ */
    import type { Equal, Expect } from '@type-challenges/utils'
    
    type Case1 = AppendArgument<(a: number, b: string) => number, boolean>
    type Result1 = (a: number, b: string, x: boolean) => number
    
    type Case2 = AppendArgument<() => void, undefined>
    type Result2 = (x: undefined) => void
    
    type cases = [
      Expect<Equal<Case1, Result1>>,
      Expect<Equal<Case2, Result2>>,
      // @ts-expect-error
      AppendArgument<unknown, undefined>,
    ]

     

     먼저, 삼항 연산자를 사용해 Fn이 함수 타입이 아니라면 never을 반환해 보자.

    type AppendArgument<Fn extends Function, A> = Fn extends (...args: infer Args) => infer T? T : never;

     

    반환해야 할 것은 함수의 반환값 타입만이 아닌 Fn의 매개변수에 A를 더한 새로운 함수므로 T를 아래와 같이 수정한다.

    (...args : [...Args, A]) => T

     

    기존 argument에 A를 추가하고, Fn의 반환값인 T를 그대로 반환한다.

    최종적으로 정답은 아래와 같다.

    type AppendArgument<Fn extends Function, A> = Fn extends (...args : infer Args) => infer T ? (...args : [...Args, A]) => T : never;

     

     

     

    참고자료

    https://github.com/type-challenges/type-challenges/blob/main/questions/00108-medium-trim/README.ko.md

    https://github.com/type-challenges/type-challenges/blob/main/questions/00110-medium-capitalize/README.ko.md

    https://github.com/type-challenges/type-challenges/blob/main/questions/00116-medium-replace/README.ko.md

    https://github.com/type-challenges/type-challenges/blob/main/questions/00119-medium-replaceall/README.ko.md

    https://github.com/type-challenges/type-challenges/blob/main/questions/00191-medium-append-argument/README.ko.md

    댓글

🍀 Y0ungZ dev blog.
스크롤 버튼