본문 바로가기
Language/Typescript

타입챌린지 : 898-Includes (easy)

by hsloth 2023. 3. 5.

 

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

 

https://github.com/type-challenges/type-challenges/blob/main/questions/00898-easy-includes/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

 

 

type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : false;

type Includes<T extends readonly any[], U> = T extends [infer F, ...infer O] ? 
	Equal<F, U> extends true ? 
    	true: Includes<O, U> : false;

// test case
type cases = [
  Expect<Equal<Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Kars'>, true>>,
  Expect<Equal<Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Dio'>, false>>,
  Expect<Equal<Includes<[1, 2, 3, 5, 6, 7], 7>, true>>,
  Expect<Equal<Includes<[1, 2, 3, 5, 6, 7], 4>, false>>,
  Expect<Equal<Includes<[1, 2, 3], 2>, true>>,
  Expect<Equal<Includes<[1, 2, 3], 1>, true>>,
  Expect<Equal<Includes<[{}], { a: 'A' }>, false>>,
  Expect<Equal<Includes<[boolean, 2, 3, 5, 6, 7], false>, false>>,
  Expect<Equal<Includes<[true, 2, 3, 5, 6, 7], boolean>, false>>,
  Expect<Equal<Includes<[false, 2, 3, 5, 6, 7], false>, true>>,
  Expect<Equal<Includes<[{ a: 'A' }], { readonly a: 'A' }>, false>>,
  Expect<Equal<Includes<[{ readonly a: 'A' }], { a: 'A' }>, false>>,
  Expect<Equal<Includes<[1], 1 | 2>, false>>,
  Expect<Equal<Includes<[1 | 2], 1>, false>>,
  Expect<Equal<Includes<[null], undefined>, false>>,
  Expect<Equal<Includes<[undefined], null>, false>>,
]

type Includes : Includes라는 타입을 정의한다.

<T extends readonly any[], U> : any타입의 원소를 갖는 상수 배열을 extends 받는 T와 U를 정의한다.

T extends [infer F, ...infer O] ? : 만약 T가 첫 번째 원소인 infer F와 나머지 배열인 infer O로 나뉜다면

Equal<F, U> extends true ? : 첫 번째 원소 F와 U가 동일한지 확인하고 만약 true를 반환한다면

true : Includes<O, U> : false; : true를 반환하고, F와 U가 다르면 Include<O, U>를 실행하고, 그것도 아니라면 false를 반환한다.

 

여기서 Equal의 정의를 보면 코드 맨위 줄과 같다.

type Equal<X, Y> : X와 Y라는 제네릭 인자를 가진 Equal이라는 타입을 정의한다.

(<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : false

여기서 고민을 조금 했다. extends X 가 T만 해당되는건지, 아니면 <T>() => T 가 전부 해당되는 건지... 그래서 지인 찬스를 사용했는데, extends X가 함수에 적용될거라면, 함수 바깥에 괄호가 씌어져 있어야 한다고 한다. (<T>() => T) extends X 와 같이 말이다. 결론적으로 extends X는 T를 꾸미는 것이었다!

T가 X와 같으면 1을 리턴하고 아니면 2를 리턴하는 함수T가 Y와 같으면 1을 리턴하고 아니면 2를 리턴하는 함수와 같다면 true를 아니라면 false를 리턴한다.

  • 참고로 앞부분의 T와 뒷부분의 T는 별개의 T이므로 (<T>() => T extends X ? 1 : 2) extends (<Z>() => Z extends Y ? 1 : 2) ? true : false 같이 작성해도 상관 없다.

참고로 extends는 편의상 '같다'라고 해석한 것이지 절대 같다는 뜻이 아니다. X extends Y 하면 보통 X는 Y를 만족해야한다. 이런 느낌이다. ex) { a: 1, b: 2 } extends { a: 1 }  같은 느낌이다. { a: 1, b: 2 } 는 { a: 1 }를 가져야 한다. 라는 느낌 이랄까. 이해가 안되셨다면 죄송하다...ㅠㅜ

Equal에 대한 자세한 설명은 아래 블로그를 보자.

https://kscodebase.tistory.com/643

 

Equal type 설명하기

[Feature request]type level equal operator · Issue #27024 · microsoft/TypeScript Search Terms Type System Equal Suggestion T1 == T2 Use Cases TypeScript type system is highly functional. Type level testing is required. However, we can not easily check ty

kscodebase.tistory.com

아니면 내가 써 놓은 글이 있는데... 내 뇌피셜이 잔뜩 들었지만, 초보자가 이해하기 쉬울거라고 생각한다. 아마도.

https://suloth.tistory.com/36

 

타입챌린지 : Equal - 번외

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

suloth.tistory.com

 

'Language > Typescript' 카테고리의 다른 글

타입챌린지 : 3057-Push (easy)  (0) 2023.03.06
타입챌린지 : Equal - 번외  (0) 2023.03.06
타입챌린지 : 533-Concat (easy)  (0) 2023.03.04
타입챌린지 : 268-If (easy)  (0) 2023.03.04
타입챌린지 : 189-Awaited (easy)  (0) 2023.03.03