Typescript类型体操 - ReplaceKeys

题目

中文

实现一个ReplaceKeys类型, 这个类型可以替换联合类型中指定属性的类型, 如果联合类型中的某个类型没有这个属性, 那就跳过; ReplaceKeys接受 3 个泛型参数.

例如:

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

English

Implement a type ReplaceKeys, that replace keys in union types, if some type has not this key, just skip replacing,
A type takes three arguments.

For example:

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

答案

type ReplaceKeys<
    U extends object,
    T extends string,
    Y extends object
> = U extends U
    ? {
          [P in keyof U]: P extends T
              ? P extends keyof Y
                  ? Y[P]
                  : never
              : U[P];
      }
    : never;

在线演示

posted @ 2022-09-18 19:16  Laggage  阅读(74)  评论(0编辑  收藏  举报