이 글은 제가 타입챌린지를 하면서 해석한 내용을 적는 글입니다. 틀린 내용이 있으면 댓글 달아주시면 감사하겠습니다.
제네릭 인자로 받은 타입의 key값을 바꾸는 타입이다. 솔직히 왜 이런 타입을 만든지는 잘 모르겠다.
type ReplaceKeys<U, T, Y> = {
[P in keyof U]: T extends keyof Y ?
P extends keyof Y ? Y[P] : U[P] :
P extends T ? never : U[P];
}
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
type NodeA = {
type: 'A'
name: string
flag: number
}
type NodeB = {
type: 'B'
id: number
flag: number
}
type NodeC = {
type: 'C'
name: string
flag: number
}
type ReplacedNodeA = {
type: 'A'
name: number
flag: string
}
type ReplacedNodeB = {
type: 'B'
id: number
flag: string
}
type ReplacedNodeC = {
type: 'C'
name: number
flag: string
}
type NoNameNodeA = {
type: 'A'
flag: number
name: never
}
type NoNameNodeC = {
type: 'C'
flag: number
name: never
}
type Nodes = NodeA | NodeB | NodeC
type ReplacedNodes = ReplacedNodeA | ReplacedNodeB | ReplacedNodeC
type NodesNoName = NoNameNodeA | NoNameNodeC | NodeB
type cases = [
Expect<Equal<ReplaceKeys<Nodes, 'name' | 'flag', { name: number; flag: string }>, ReplacedNodes>>,
Expect<Equal<ReplaceKeys<Nodes, 'name', { aa: number }>, NodesNoName>>,
]
답은 생각보다 간단하다.
[P in keyof U] : 타입 U의 키들을 P라고 정의한다.
T extends keyof Y ? P extends keyof Y ? Y[P] : U[P] : T가 Y의 키값이고, P가 Y의 키값이면, Y[P]를 리턴한다(변화된 타입을 리턴). 만약 P가 Y의 키값이 아니라면 U[P]를 리턴한다(변화되지 않은 값 리턴)
P extends T ? never : U[P] : T가 Y의 키값이 아니고, P가 T와 같다면, never를 리턴한다(두 번째 케이스를 통과하기 위해 설정해주었다) 만약 P와 T가 다르다면 U[P]를 리턴한다.
찾아보니 더 쉬운 방법도 있었다..
type ReplaceKeys<U, T, Y> = {
[K in keyof U]: K extends T ? K extends keyof Y ? Y[K] : never : U[K]
}
extends를 적절히 사용해주면 다음과 같이 표현도 가능하다.
'Language > Typescript' 카테고리의 다른 글
타입챌린지 : 1978-Percentage Parser (medium) (0) | 2023.04.27 |
---|---|
타입챌린지 : 1367-Remove Index Signature (medium) (0) | 2023.04.24 |
타입챌린지 : 1097-IsUnion (medium) (0) | 2023.04.21 |
타입챌린지 : 1042-IsNever (medium) (0) | 2023.04.19 |
타입챌린지 : 949-AnyOf (medium) (0) | 2023.04.18 |