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;

在線演示

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章