3장, lib.es5.d.ts 분석하기
in Study
3.1 Partial, Required, Readonly, Pick, Record
- Partial
- 기존 객체의 속성을 전부 옵셔널로 만들어 버리는 함수
type Partial<T>={
[P in keyof T]?:T[P]
}
- Required
- 반대로 모든 속성값을 필수로 만들어버리는 함수
type Required<T>={
[P in keyof T]-?:T[P];
}
- Readonly
- 모든 속성을 readonly로 만들어버리기
type Readonly<T>={
readonly [P in keyof T]:T[P];
}
- 모든 속성을 readonly가 아니게 만들어버리기
type NotReadonly<T>={
-readonly [P in keyof T]: T[P];
}
- Pick
- 지정한 속성 값만 추리기
type Pick<T,K extends keyof T> = {
[P in K]:T[P];
}
- K값이 T안에 속하지 않은 key 값이 들어갈 때, 지정한 속성 값만 추리기
type Pick<T,K> = {
[P in (K extends keyof T ? K : never)]:T[P]
}
- Record
- 모든 속성의 타입이 동일한 객체의 타입만들기
type Record<K extends keyof any,T> = {
[P in K]: T;
}
3.2 Exclude, Extract, Omit, NonNullable
- 컨디셔널 타입일 때, 유니언인 기존 타입과 제네릭이 만나면 분배법칙이 실행된다
- Exclude
- 어떠한 타입에서 지정한 타입을 제거하는 함수
type Exclude<T,U> = T extends U ? never : T;
type Result = Exclude<1|'2'|3,string>;
- Extract
- 어떠한 타입에서 지정한 타입만 추리는 함수
type Extract<T,U> = T extends U ? T : never;
type Result<1|'2'|3,string>; // '2'
- Omit
- 특정 객체에서 지정한 속성을 제거하는 함수
- Pick 과 Exclude 타입을 활용
type Omit<T,K extends keyof any> = Pick<T,Exclude<keyof T,K>>;
type Result = Omit<{a:'1',b:2,c:true},'a'|'c'>;
- NonNullable
- 예전 버전
type NonNullable<T> = T extends null | undefined ? never : T;
- 현재
- {} 는 null과 undefined를 포함하지 않는 타입
- T 와 {}의 교집합
type NonNullable<T> = T & {};
3.3 Parameters, ConstructorParameters, ReturnType, InstanceType
- Parameters
- 함수 매개변수 타입
type Parameters<T extends (...args:any)=>any> =
T extends (...args:infer P)=> any ? P : never;
- ConstructorParameters
- 생성자 함수의 매개변수 타입
type ConstructorParameters<T extends abstract new (...args:any)=>any> = T extends abstract new (...args:infer P)=> any ? P : never;
- ReturnType
- 함수 반환 값 타입
type ReturnType<T extends (...args:any)=>any> =
T extends (...args:any)=> infer R ? R : any;
- InstaceType
- 생성자 함수로 만든 인스턴스 타입
type InstanceType<T extends abstract new (...args:any)=>any> =
T extends abstract new (...args:any)=> Infer R ? R : any;
3.4 ⚪ ThisType
- 메서드들에 this를 정해주는 타입
- lib.ex5.d.ts에 정의되어있지 않음 ⇒ 내부 구현이 특별하게 처리되어 있음
type Data = {money:number};
type Methods = {
addMoney(amount:number):void;
useMoney(amount:number):void;
}
type Obj = {
data: Data;
methods: Methods & **ThisType<Data & Methods>**;
}
const obj:Obj = {
data:{
money: 0,
},
methods:{
addMoney(amount){
this.money += amount;
}
useMoney(amount){
this.money -= amount;
}
}
}
참고
- UpperCase, LowerCase, Capitalize, UnCapitalize 타입도 내부적으로 따로 구현되어있음
3.9 flat 분석하기
- flat은 한 배열의 차원을 한 단계 씩 낮추는 메서드
type FlatArray<Arr,Depth extends number>={
"done" : Arr,
"recur" : Arr extends ReadonlyArray<infer InnerArr>
? FlatArray<InnerArr,[-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20][Depth]>
: Arr
}[Depth extends -1 ? "done" : "recuer"];
interface Array<T>{
flat<A,D extends number = 1>(this:A,depth?:D):FlatArray<A,D>[]
}
- A는 this 타입으로 원본 배열을 의미
- D는 flat 메서드의 매개변수인 낮출 차원 수
- 차원이 몇 차원이다.. 의미가 아님!!
- 재귀적으로 FlatArray 타입을 계속 호출하여 배열의 차원 수를 낮춰감..
- Depth를 낮춰가면서 인덱스 접근 타입[-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]의 인덱스 값에 접근
- Depth 값이 -1이 되면 flat 재귀를 멈추고 “done” // 완료
3.10 Promise, Awaited 타입 분석하기
- lib.es5.d.ts 파일을 살펴보자
type Awaited<T> =
T extends null | undefined ? T :
T extends object & { then(onfulfilled: infer F,...args: infer -) : any } ?
F extends ((value:infer V,...args: infer _) => any) ?
Awaited<V> : never : T;
- **규칙 1번. Awaited<객체가 아닌="" 값=""> === 객체가 아닌 값** 객체가>
- Awaited
일 때, T extends null undefined 는 false 이고, - T extends object & {then(onfulfilled:infer F,…args: infer_):any ⇒ 객체이며 then 메서드를 가지고 있지 않으므로 false 가 되어 T 가 된다.
- Awaited
- **규칙 1번. Awaited<객체가 아닌="" 값=""> === 객체가 아닌 값** 객체가>
- **규칙 2번. Awaited(Promise
> === Awaited ** - Awaited<Promise
> 일 때, T extends null undefined 는 false 이고, - T extends object & {then(onfulfilled:infer F,…args:infer_):any ⇒ 객체이며 Promise 인스턴스 타입이 then 메서드를 가지고 있으므로 true이고 infer F 는 then메서드 안의 콜백함수를 가리킨다
- F extends ((value:infer V,…args:infer_)⇒any) 콜백함수와 같게 생겼으므로 true이며,
- then메서드 안의 콜백함수의 인자 값 V를 추론하여 Awaited
가 된다 - 사실.. Promise
이므로 then 콜백메서드 안의 인자값도 string이 된다.
- Awaited<Promise
- **규칙 2번. Awaited(Promise
3.11 lib.es5.d.ts 분석하기
- CallableFunction은 호출할 수 있는 함수, NewableFunction 은 new를 붙여 호출할 수 있는 함수
- 클래스에서의 bind : 클래스에서는 this 를 bind 하는 것을 무시하므로, OmitThisParameter를 반환하지 않음..
- ThisParameterType
- this 값 가져오는 타입
- 만약 this값이 없다면 unknown 이다..
inferface CallableFunction extends Function {
bind<T>(this:T,thisArg: ThisParameterType<T>): OmitThisParameter<T>;
}
this ThisParameterType<T> = T extends (this: infer U,...args:never)=> any ?
U : unknown;
type OmitThisParameter<T> = unknown extends ThisParameterType<T> ? T : T extends
(...args:infer A) => infer R ? (...args:A) => R : T;
- OmitThisParameter
- this 값이 없으면 unknown
- this 값이 있고 this가 함수 형태 일 때, this값을 제거한 함수 형태만 반환
참고
- bind, call, apply 의 타입은 strict 옵션이 활성화 있을 때에만 검사한다..
- strictBindCallApply 옵션임
- 이 옵션을 해제하면 bind,call,apply 타입 검사를 하지 않음