Partial<T>
T 타입안에 요소들에 대해서 전부 Optional(?:)로 만들어 준다.
interface Myinfo {
name: string,
age: number,
phone: number,
married: boolean,
}
const jeongmin : Myinfo ={
name: "jeongmin",
age: 26,
phone: 12345678,
married: false,
}
const newJeongmin : Partial<Myinfo> ={
name: "jeongmin",
age: 26,
}
Partial을 뜯어서 구현을 해자보자면 P<T>으로 지정해줬을 때,
key값은 해당 T 타입의 키값들을 가져와 in 으로 돌려서 순회해서 뽑아내고 [ Key in keyof T ]
value값은 T타입에 인덱싱을 해서 가져온다. T[Key]
interface Myinfo {
name: string,
age: number,
phone: number,
married: boolean,
}
type P<T> = {
[Key in keyof T]?: T[Key]
}
const newJeongmin : P<Myinfo> ={
name: "evan"
}
하지만 아무것도 모든 요소를 Optional로 만들어버리면 아무것도 안넣어도 에러를 발생시키지 않기때문에 선호되지 않는다. 그래서 Pick, Omit을 쓰게 되는데, 쉽게말하면 whitelist랑 blacklist같은거라고 할 수 있다.
Pick<T>, Omit<T>
interface Myinfo {
name: string,
age: number,
phone: number,
married: boolean,
}
const newJeongmin : Pick<Myinfo, 'name'> ={
name: "jeongmin",
}
const newJeongmin2 : Omit<Myinfo, 'name'> ={
age: 26,
phone: 34568945,
married: false,
}
Pick을 뜯어서 구현해보자면
일단 타입을 P<T, S>로 해주는데 S가 무조건 T안에 들어있어야하는 key값이기 때문에 조건을 걸어줘야한다. 그러면 P<T, S extends keyof T> 로 쓸수 있고, key값은 S가 자체가 key값이기때문에 S만 순회해주면된다. 그래서 [Key in S]이고, value값은 T에서 Key값을 인덱싱을 해주어서 구해주면 되기때문에 최종적으로는 밑에처럼 구현 할 수 있다.
type P<T, S extends keyof T> = {
[Key in S]: T[Key]
}
const newJeongmin3 : P<Myinfo, 'name'> ={
name: "jeongmin",
}
Omit을 뜯어서 구현해보자
일단 Omit을 해보기 앞서, Exclude<T, S>를 알아야하는데,
type A = Exclude<keyof Myinfo, 'name'>
// type A = 'age' | 'phone' | 'married'
//lib.es5.d.ts
type Exclude<T, U> = T extends U ? never : T;
Exclude는 S가 key값이라면 T에 keyof를 붙여서 key들중에서 S만뺀 key값들을 반환한다. 그 key값들을 Pick으로 가져오면 그게 Omit타입이된다. 하지만 마지막으로 S또한 T안에 있어야하는 놈이기에 extends keyof T로 방어해준다.
type O<T, S extends keyof T> = Pick<T, Exclude<keyof T, S>>
const newJeongmin3: O<Myinfo, 'name'> = {
age: 26,
phone: 3456783,
married: false,
}
Required<T>
Require 타입은 간단히, optional이든 뭐든 상관없이 모든 속성들을 Require로 바꿔준다. 사용하기엔 쉬운데 분해해보면 새로운 개념이 나온다고 한다. 위에서 Partial<T>를 보면 모든 속성을 순회하면서 optional로 바꿔주는데, 이것은 그 방식을 차용하지만 수정자를 써서 '-?' 를 넣어서 optional을 무조건적으로 지워준다.
type R<T> = {
[Key in keyof T]-?: T[Key];
}
Record<K, T>
Record 타입은 타입의 프로퍼티들을 다른 타입에 매핑시키는 데 사용하는데, 예를 들면 간단히 객체가 하나 있다고 한다면,
K가 key값의 타입이 되겠고, T는 value값의 타입이 될것이다. 근데 K안에 있는 타입이여야하기 때문에 extends keyof any 넣어준다.
type R<K extends keyof any, T> ={
[Key in K]: T;
}
const Obj: R<string, number> = {a:3, b:5, c:7}
NonNullable<T>
NonNullable타입은 T에서 null 과 undefined를 제외한 타입을 만들어줍니다.
type A = string | null | undefined | boolean
type NoFalsy = NonNullable<A>
// type NoFalsy = string | boolean
Parameters<T>
함수 타입 T의 매개변수 타입들의 튜플 타입을 구성합니다.
function zip(x: number, y: string, z: boolean): { x: number, y: string, z: boolean}{
return {x,y,z};
}
type P<T extends (...arg: any) => any> = T extends (...args: infer A) => any ? A : never;
type Param = P<typeof zip>;
// type Param = [x: number, y: string, z: boolean];
ReturnType<T>
함수 T의 반환 타입으로 구성된 타입을 만듭니다.
function zip(x: number, y: string, z: boolean): { x: number, y: string, z: boolean}{
return {x,y,z};
}
type R<T extends (...arg: any) => any> = T extends (...args: any) => infer A ? A : never;
type Ret = R<typeof zip>;
// type Ret = { x: number; y: string; z: boolean; }