728x90
문제
Convert a property of type literal (label type) to a primitive type.
type X = { name: 'Tom', age: 30, married: false, addr: { home: '123456', phone: '13111111111' }}type Expected = { name: string, age: number, married: boolean, addr: { home: string, phone: string }}type Todo = ToPrimitive<X> // should be same as `Expected`
cases
type PersonInfo = { name: 'Tom' age: 30 married: false addr: { home: '123456' phone: '13111111111' } hobbies: ['sing', 'dance'] readonlyArr: readonly ['test'] fn: () => any fn2: (a: boolean) => any}type ExpectedResult = { name: string age: number married: boolean addr: { home: string phone: string } hobbies: [string, string] readonlyArr: readonly [string] fn: Function fn2: Function}type cases = [ Expect<Equal<ToPrimitive<PersonInfo>, ExpectedResult>>,]
정답
type ToPrimitive<T> = T extends (...arg: never[]) => unknown ? Function : T extends string ? string : T extends boolean ? boolean : T extends number ? number : T extends object ? { [key in keyof T]: ToPrimitive<T[key]> } : never
풀이
조건
- 모든 타입을
Primitive
로 변경한다.
- object, array 타입은 내부의 요소까지
Primitive
로 변경한다.
해설
우선 Primitive 타입 3가지 number, string, boolean을 확인해서 반환하는 로직을 구현한다.
type ToPrimitive<T> = T extends string ? string
: T extends boolean ? boolean
: T extends number ? number
: T
object타입인 경우, 재귀를 이용해서 변환한다.
type ToPrimitive<T> = T extends string ? string : T extends boolean ? boolean : T extends number ? number : T extends object ? { [key in keyof T]: ToPrimitive<T[key]> } : never
object 의 하위 타입 중 function 은 별도로 처리해준다.
type ToPrimitive<T> = T extends (...arg: never[]) => unknown ? Function : T extends string ? string : T extends boolean ? boolean : T extends number ? number : T extends object ? { [key in keyof T]: ToPrimitive<T[key]> } : never
리팩토링
1번에서 구현한 부분을 다음과 같이 수정한다.
T extends { valueOf: () => infer P } ? P : T
모든 타입은 valueOf라는 함수를 가지게 되는데, 이 때 반환 하는 값을 infer P로 받아 반환할 수 있다.
따라서 이를 조합하면 다음과 같다.
type ToPrimitive<T> = T extends (...arg: never[]) => unknown ? Function : T extends object ? { [key in keyof T]: ToPrimitive<T[key]> } : T extends { valueOf: () => infer P } ? P : T
참조 : https://github.com/type-challenges/type-challenges/issues/22057
혹시 오류나 개선점이 있다면 댓글 부탁드리겠습니다.
728x90
'FE > type-challenge' 카테고리의 다른 글
18220. Filter (0) | 2023.10.06 |
---|---|
18142. All (0) | 2023.09.25 |
9898. FindEles (0) | 2023.09.19 |
10969. Integer (0) | 2023.09.15 |
9896. GetMiddleElement (0) | 2023.09.12 |