T에서 K 프로퍼티만 선택해 새로운 오브젝트 타입을 만드는 내장 제네릭 Pick<T, K>을 이를 사용하지 않고 구현하세요.
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = MyPick<Todo, 'title' | 'completed'>
const todo: TodoPreview = {
title: 'Clean room',
completed: false,
}
정답
type MyPick<T, K keyof T> = {[P in K]: T[P]};
keyof T
여기서 keyof T가 핵심.
K 는 T의 키의 일부여야하기 때문에 이러한 제약 조건을 둬야한다.
Mapped Type
K는 유니온 타입. in 은 for…in과 같이 동작합니다. 따라서 ‘title’ | ‘completed’ 를 순환해서 P에 변수를 선언한다고 생각하면 됨.
T의 모든 프로퍼티를 읽기 전용(재할당 불가)으로 바꾸는 내장 제네릭 Readonly<T>를 이를 사용하지 않고 구현하세요.
interface Todo {
title: string
description: string
}
const todo: MyReadonly<Todo> = {
title: "Hey",
description: "foobar"
}
todo.title = "Hello" // Error: cannot reassign a readonly property
todo.description = "barFoo" // Error: cannot reassign a readonly property
정답
type MyReadonly<T> = {
readonly [P in keyof T]: T[P];
}
keyof T
T의 key를 P에 선언해줘야함.
배열(튜플)을 받아, 각 원소의 값을 key/value로 갖는 오브젝트 타입을 반환하는 타입을 구현하세요.
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'}
정답
type TupleToObject<T extends PropertyKey[]> = {[P in T[number]: P};
PropertyKey?
객체의 키에 올 수 있는 타입을 타입스크립트 내에서 선언해둔것.
string | number | symbol 이라고 함.
T[number]
배열 타입 T에 인덱스 접근 이라고 함. 이러면 배열 안에 잇는 모든 요소들의 타입이 유니온으로 추출됨.
이때 배열이 일반 배열인지 튜플인지에 따라서 결과가 다르게 나온다고 함.
일반 배열
type FruitList = string[];
type Fruit = FruitList[number];
// string;
배열 0번째도 string, 100번째, 1000번째도 string이니까 타입은 string이 된다.
튜플일 경우 (as const)
const fruitList = ['banana', 'apple', 'grape'] as const;
type Fruit = typeof fruitList[number];
// 'banana' | 'apple' | 'grape'
값을 타입으로 변환하고 싶을때 사용한다.
typeof fruitList ⇒ readonly [’banana’, ‘apple’, ‘grape’]
[number]로 접근하게 되면 타입스크립트는 0번째엔 banana, 1번째는 apple.. 그래서 유니온 타입으로 반환이 되는 것이다.