본문 바로가기
Language/Typescript

타입챌린지 : 119-ReplaceAll (medium)

by hsloth 2023. 3. 31.

 

이 글은 제가 타입챌린지를 하면서 해석한 내용을 적는 글입니다. 틀린 내용이 있으면 댓글 달아주시면 감사하겠습니다.

 

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

 

GitHub - type-challenges/type-challenges: Collection of TypeScript type challenges with online judge

Collection of TypeScript type challenges with online judge - GitHub - type-challenges/type-challenges: Collection of TypeScript type challenges with online judge

github.com

 

Replace와는 다르게 모든 From을 To로 바꾸는 타입이다.

 

Replace는 아래 포스팅을 참고하자.

https://suloth.tistory.com/62

 

타입챌린지 : 116-Replace (medium)

이 글은 제가 타입챌린지를 하면서 해석한 내용을 적는 글입니다. 틀린 내용이 있으면 댓글 달아주시면 감사하겠습니다. https://github.com/type-challenges/type-challenges/blob/main/questions/00116-medium-replace/REA

suloth.tistory.com

 

처음 생각했던 답

// 오답
type ReplaceAll<S extends string, From extends string, To extends string> = 
  From extends '' ? S : S extends `${infer F}${From}${infer L}` ?
    ReplaceAll<`${F}${To}${L}`, From, To> : 
    S;

이렇게 하면 ReplaceAll<`${F}${To}${L}`, From, To> 에서 변형된 문자열 전체를 한 번 더 Replace하기 때문에 안된다.

 

그래서 다음과 같이 답을 작성할 수 있다.

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

/* _____________ Test Cases _____________ */
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<'', '', ''>, ''>>,
]

 

From extends '' ? S : From이 빈문자열이면 S를 그대로 리턴한다.

S extends `${infer F}${From}${infer L}` ? : S에 중간에 From이 들어간다면,

`${F}${To}${ReplaceAll<L, From, To>}` : S; : 변환된 문자열 + 뒷 문자열을 ReplaceAll 한 문장을 반환한다. 아니라면 S를 반환한다.