Week 7
Medium-645-Diff
type Diff<O, O1> = Omit<O & O1, keyof (O | O1)>;
O & O1을 통해 두 객체가 가진 key 값을 모두 포함할 수 있는 객체를 생성하고, 중복되는 key를 제거하는 형태O & O1은 객체간의 인터섹션으로, 객체의 인터섹션은 모든 키를 포함하는 객체를 생성한다. (동일한 key가 있다면, 해당 key의 value의 타입은 O[key]와 O1[key]가 intersection된 타입을 갖게 된다.)keyof (O | O1)은O | O1연산을 먼저 수행하고keyof연산을 수행하며,keyof연산은 유니언 타입에 대해 실행되면, 유니언 구성원이 공통으로 갖는 키만을 반환한다.keyof O | keyof O1은O와O1의 키가 모두 포함된 유니언을 반환한다. (모든 key값을 얻고자 할때 사용할 수 있다)
Medium-949-AnyOf
Python의any()함수는 전달된 Iterable의 요소가 하나라도 참인 경우 true를 반환한다.
// 시행착오 1
type FalsyLiteral = 0 | "" | false | [] | {} | undefined | null;
type AnyOf<T extends any[], Result extends boolean = false> = T extends [
infer F,
...infer R
]
? F extends FalsyLiteral
? AnyOf<R, false>
: AnyOf<R, true>
: Result;
- 누적 처리 오류: 앞에서 true로 처리되었어도, 뒤에서 false로 처리되면 결과가 false로 나오게 됨
// 시행착오 2
type FalsyLiteral = 0 | "" | false | [] | {} | undefined | null;
type AnyOf<T extends any[], Result extends boolean = false> = T extends [
infer F,
...infer R
]
? F extends FalsyLiteral
? Result extends true
? Result
: AnyOf<R, false>
: AnyOf<R, true>
: Result;
- FalsyLiteral의 빈 객체 타입을 처리를 다르게 해야 함
{}빈 객체는 타입스크립트에서 거의 모든 값(숫자, 불리언, 문자열 배열 등)을 포함할 수 있는 타입
type FalsyLiteral =
| 0
| ""
| false
| []
| undefined
| null
| { [key: keyof any]: never };
type AnyOf<T extends any[], Result extends boolean = false> = T extends [
infer F,
...infer R
]
? F extends FalsyLiteral
? Result extends true
? Result
: AnyOf<R, false>
: AnyOf<R, true>
: Result;
{ [key: keyof any]: never }는 명시적으로 빈 객체를 표현할 수 있는 타입infer F, ...infer R형태로 재귀를 통해 처리하며, 순차적으로 요소를 확인하여 FalsyLiteral을 확인하되Result가 이미 true인 경우 즉시 반환하도록 처리
Medium-1042-IsNever
type IsNever<T> = [T] extends [never] ? true : false;
- 지난 Week 5의
Permutation에서 이용했던 방법 [T]를 통해 타입 T를 배열 혹은 튜플로 묶어never를 만나 평가를 중단하지 않도록 하고extends [never]을 통해never타입인 경우 true, 그렇지 않은 경우 false를 반환
Medium-1097-IsUnion
type IsUnion<T, U = T> = T extends any
? [U] extends [T]
? false
: true
: never;
T extends any는 유니언 타입에 대해 분배 법칙을 적용하기 위한 조건[U]는 원본 타입을 보존하고 있으며,[T]는 분배된 개별 타입유니언 타입이 아닌 경우:
[U] extends [T]가 항상 true가 되어 false를 반환유니언 타입인 경우: 분배된
T의 개별 타입과 원본U를 비교할 때[U] extends [T]가 false가 되어 true를 반환예시: T가
string | number인 경우- T는
string과number로 분배되고고 [string | number] extends [string]은false[string | number] extends [number]은false- 따라서
true를 반환하여 유니언 타입임을 판별한다
- T는
Medium-1130-ReplaceKeys
type ReplaceKeys<U, T, Y extends { [key: keyof any]: any }> = U extends U
? { [K in keyof U]: K extends T ? Y[K & keyof Y] : U[K] }
: never;
U extends U는 타입 U가 자기 자신인 경우 true를 반환하며, 이는 유니언 타입인 경우 분배를 유도하는 방식{ [K in keyof U]: K extends T ? Y[K & keyof Y] : U[K] }는 타입 U의 모든 키를 순회하며, 키 K가 T와 일치하는 경우 Y의 키로 대체하고, 그렇지 않은 경우 원래 키 K를 유지하는 형태- 이 때,
[K & keyof Y]는 K가 Y에 존재하는 key라면,Y[K]타입으로 교체를 진행하고, 그렇지 않은 경우 [K & keyof Y]는 존재하지 않는 키이므로never로 평가되어,Y[never]가 되어K: never로 평가된다.
Medium-1367-RemoveIndexSignature
type RemoveIndexSignature<T> = {
[K in keyof T as string extends K
? never
: number extends K
? never
: symbol extends K
? never
: K]: T[K];
};
K는keyof T에 해당하는 키 값이다index signature는 객체 내 반복되는 키-밸류 형태를 나타내기 위해 이용되며, 리터럴 타입이 아닌 일반적인 타입을 이용한다.PropertyKey로 이용되는string | number | symbol타입으로 나타나는 K, 즉 인덱스 시그니처인 K를 제외하기 위해string extends K,number extends K,symbol extends K조건을 이용하며, 리터럴 타입이 아닌 K를 제외한다.