✍ 공부/TypeScript
[type-challenges] IsNever
Po_tta_tt0
2023. 7. 4. 23:56
반응형
문제
input type으로 T를 받는 IsNever type을 구현하십시오. 만약 T의 유형이 never으로 확인되면 true를 반환하고 아니면 false를 반환합니다
설명
/* _____________ Your Code Here _____________ */
type IsNever<T> = [T] extends [never] ? true : false
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<IsNever<never>, true>>,
Expect<Equal<IsNever<never | string>, false>>,
Expect<Equal<IsNever<''>, false>>,
Expect<Equal<IsNever<undefined>, false>>,
Expect<Equal<IsNever<null>, false>>,
Expect<Equal<IsNever<[]>, false>>,
Expect<Equal<IsNever<{}>, false>>,
]
왜 [T]
와 [never]
일까?
type IsNever<T> = T extends never ? 'a' : 'b'
type t = IsNever<never> // never
type Never<T> = T extends any ? '무엇인가 출력' : '다른 무엇인가 출력'
type temp = Never<never> // never
그런데
type P = never extends never ? 'yes' : 'no' // yes
이 type P는 'yes'를 출력한다.
제네릭 타입에 비밀이 있는게 분명하다
공식문서를 보자
type ToArray<Type> = Type extends any ? Type[] : never;
type StrArrOrNumArr = ToArray<string | number>; // type StrArrOrNumArr = string[] | number[]
이 된다
이는, <string | number>
유니언에 있는 멤버 타입들을 모두 돌며 ToArray<T>
를 실행시켰기 때문이다.
따라서
type StrArrOrNumArr = ToArray<string | number>// 의 결과는
type a = ToArray<string> | ToArray<number>; // 와 같다
이러한 📍분배 조건부 유형을 피하기 위해
type ToArrayNonDist<Type> = [Type] extends [any] ? Type[] : never;
type StrArrOrNumArr = ToArrayNonDist<string | number>; // (string | number)[]
처럼 extends 키워드의 양 옆을 []
로 감싸주어 해결할 수 있다.
그럼 never은? union이 아니었는데? 참고
타입스크립트는 조건 타입내부에 있는 유니온 타입을 자동으로 결정한다.
따라서 never은 비어있는 union으로 인식된다(멤버가 없는 유니언)
결국type IsNever<T> = T extends never ? true : false
라고 작성했을 시,
타입스크립트는 T로 들어온 never은 빈 유니온으로 확인하고 never을 반환하는 것!
아하! 🥳
따라서 분배 조건부(never을 빈 union으로 인식하지 못하기 위해) 유형을 피하기 위해
extends의 키워드의 양 옆을 []
로 감싸주는 것!
반응형