본문 바로가기

FE/type-challenge

16259. ToPrimitive

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

풀이

조건

  1. 모든 타입을 Primitive 로 변경한다.
  1. 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