跳到主要内容

ReplaceKeys

介绍

实现一个ReplaceKeys类型, 代替联合类型中的keys, 如果类型中没有这个key, 跳过替换. 类型会接收3个参数

例如:

ts
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 Nodes = NodeA | NodeB | NodeC
type ReplacedNodes = ReplaceKeys<
Nodes,
"name" | "flag",
{ name: number; flag: string }
> // {type: 'A', name: number, flag: string} | {type: 'B', id: number, flag: string} | {type: 'C', name: number, flag: string} // would replace name from string to number, replace flag from number to string.
type ReplacedNotExistKeys = ReplaceKeys<Nodes, "name", { aa: number }> // {type: 'A', name: never, flag: number} | NodeB | {type: 'C', name: never, flag: number} // would replace name to never
ts
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 Nodes = NodeA | NodeB | NodeC
type ReplacedNodes = ReplaceKeys<
Nodes,
"name" | "flag",
{ name: number; flag: string }
> // {type: 'A', name: number, flag: string} | {type: 'B', id: number, flag: string} | {type: 'C', name: number, flag: string} // would replace name from string to number, replace flag from number to string.
type ReplacedNotExistKeys = ReplaceKeys<Nodes, "name", { aa: number }> // {type: 'A', name: never, flag: number} | NodeB | {type: 'C', name: never, flag: number} // would replace name to never
View on GitHub

起点

ts
/* _____________ Your Code Here _____________ */
 
type ReplaceKeys<U, T, Y> = any
 
/* _____________ Test Cases _____________ */
 
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>>,
Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.
Expect<Equal<ReplaceKeys<Nodes, 'name', { aa: number }>, NodesNoName>>,
Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.
]
 
ts
/* _____________ Your Code Here _____________ */
 
type ReplaceKeys<U, T, Y> = any
 
/* _____________ Test Cases _____________ */
 
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>>,
Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.
Expect<Equal<ReplaceKeys<Nodes, 'name', { aa: number }>, NodesNoName>>,
Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.
]
 
take the challenge

解决方案

Spoiler warning // Click to reveal answer
ts
// most popular
type ReplaceKeys<U, T, Y> = { [K in keyof U]: K extends T ? K extends keyof Y ? Y[K] : never : U[K] }
 
 
ts
// most popular
type ReplaceKeys<U, T, Y> = { [K in keyof U]: K extends T ? K extends keyof Y ? Y[K] : never : U[K] }
 
 
view more solutions