[ TypeScript ] type-challenges - 00011-easy-tuple-to-object
00011-easy-tuple-to-object
[ 문제 설명 ]
Given an array, transform it into an object type and the key/value must be in the provided array.
[ 문제 ]
type TupleToObject<T extends readonly any[]> = any
[ 예시 ]
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const type result = TupleToObject<typeof tuple> // expected { 'tesla': 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}
시작하기 전에,,
4번과 7번 문제는 정답에 대한 설명 없이 몰랐던 지식 위주로 설명했었는데요 ..!
11번 문제부터는 몰랐던 지식과 더불어 왜 이렇게 풀어야 하는지를 좀 더 설명하도록 하겠습니다 : )
const assertion
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
예시의 tuple을 보면 ' as const '라는 것을 볼 수 있는데, 이에 대해 이야기 해보겠습니다.
우선 먼저 알아야 할 것은 let과 const의 차이에요.
let은 값을 언제든 변경할 수 있기 때문에 primitive type으로 추론이 되고,
const는 값을 변경할 수 없기 때문에 literal type으로 추론이 됩니다.
let str1 = 'str1' // string
const str2 = 'str2' // "str2"
그런데 let도 literal type으로 추론할 수 있는 방법이 있는데, 그게 바로 ' as const '입니다.
그리고 그걸 const assertion이라고 불러요.
let str1 = 'str1' as const // "str1"
그럼 여기서 하나의 의문이 들게 될거에요.
" 저렇게 할거면 그냥 const를 사용하면 되지 않나 ? "
맞아요, primitive type에선 const assertion 대신 const를 사용하는 게 효율적이죠.
혹시 객체나 배열에서 타입 추론이 어떻게 되는지 본 적 있으신가요 ?
const arr1 = ['123', '456'] // string[]
const arr2 = ['123', 456] // (string | number)[]
const arr3 = [123, 456] // number[]
const obj1 = { a: 1, b: 2 }
// {
// a: number;
// b: number;
// }
const로 선언되었지만, 속성값은 언제든지 변경할 수 있기 때문에 속성값들의 타입이 primitive type으로 추론됩니다.
객체와 배열에도 ' as const'를 사용해볼까요 ?
const arr1 = ['123', '456'] as const // readonly ["123", "456"]
const obj1 = { a: 1, b: 2 } as const
// {
// readonly a: 1;
// readonly b: 2;
// }
const obj2 = { a: 1 as const, b: 2 }
// {
// a: 1;
// b: number;
// }
primitive type으로 추론되었던 객체와 배열의 속성값들이 literal type으로 추론되었어요.
이렇게 된다면 객체와 배열에서도 타입 안정성을 보장할 수 있게 됩니다 👍👍
인덱스 접근 타입
배열과 객체인 타입들은 어떻게 접근할까요 ?
배열은 T[number], 객체는 T[string]으로 접근할 수 있습니다.
좀 더 자세히 설명해드릴게요 !
const arr = [1, 2, 3] as const; // readonly [1, 2, 3]
arr의 타입은 ' readonly [1, 2, 3] '입니다.
그리고 저희는 이 타입을 유니온 타입으로 가져오고 싶은 상황이에요.
이 때, T[number]를 사용하면 됩니다.
const arr = [1, 2, 3] as const;
type ArrType = typeof arr; // readonly [1, 2, 3]
ArrType[number] // 1 | 2 | 3
그럼 객체에서도 적용시켜볼까요 ?
객체에는 T[string]을 사용합니다.
const obj = { a: 1, b: 2 } as const;
type ObjType = typeof obj;
// {
// readonly a: 1;
// readonly b: 2;
// }
ObjType[string] // 1 | 2
[ 정답 ]
type TupleToObject<T extends readonly any[]> = { [key in T[number]]: key }
1. T는 const assertion된 배열 형태의 타입이 들어오기 때문에 'readonly any[]'를 extends 시켜준다.
2. object로 만들어야 하기 때문에 중괄호를 둘러준다.
3. 인덱스 접근 타입을 사용해 들어온 타입들을 유니온 타입으로 변경시켜준다.
4. mapped type인 in을 통해 유니온 타입을 순회하여 key: value 형태로 만들어준다.
https://medium.com/@seungha_kim_IT/typescript-3-4-const-assertion-b50a749dd53b
TypeScript 3.4: const assertion
TypeScript 3.4 버전에는 const assertion 이라는 기능이 추가되었습니다.
medium.com
Typescript에서 효과적으로 상수 관리하기
const assertion and enum
blog.toycrane.xyz