重命名 typescript 对象类型的键

Edu*_*ard 10 typescript

我有这个:

type Two = {
  one: number,
  two: string,
  three: boolean
}
Run Code Online (Sandbox Code Playgroud)

我希望它创建一个看起来像这样的类型:

type RenamedTwo = {
  one: number,
  two: string,
  four: boolean // difference
}
Run Code Online (Sandbox Code Playgroud)

试图以这种方式创建它:

type Rename<T, K extends keyof T, N> = Pick<T, Exclude<keyof T, K>> & { [N]: T[K] }
Run Code Online (Sandbox Code Playgroud)

尝试使用这种方式:

type Renamed = Rename<Two, 'three', 'four'>
Run Code Online (Sandbox Code Playgroud)

但是 TSlint 标记[N]为错误并给出以下错误消息:

[ts] 类型文字中的计算属性名称必须引用类型为文字类型或“唯一符号”类型的表达式。[ts] 'N' 仅指一种类型,但在此处用作值。

Tit*_*mir 12

您还需要为重命名的属性使用映射类型:

type Two = {
    one: number,
    two: string,
    three: boolean
}


type Rename<T, K extends keyof T, N extends string> = Pick<T, Exclude<keyof T, K>> & { [P in N]: T[K] }

type Renamed = Rename<Two, 'three', 'four'>
Run Code Online (Sandbox Code Playgroud)

请注意,如果您提供更多属性,这将无法按预期工作:

type Renamed = Rename<Two, 'two'  |'three' , 'four' | 'five'> // will be Pick<Two, "one"> & {
//    four: string | boolean;
//    five: string | boolean;
// }
Run Code Online (Sandbox Code Playgroud)


小智 12

在当前的 typescript 版本 4.6.2 中,有一个可以使用的重新映射语法。它可以更容易地实现。

操场

type RenameByT<T, U> = {
  [K in keyof U as K extends keyof T
    ? T[K] extends string
      ? T[K]
      : never
    : K]: K extends keyof U ? U[K] : never;
};

type Two = { one: number; two: string; three: boolean };

// returnType = { one: number; two: string, four: boolean };
type renameOne = RenameByT<{three: 'four', five: 'nouse'}, Two>;

// returnType = { x: number, y: string, z: boolean; }
type renameAll = RenameByT<{one: 'x', two: 'y', three: 'z'}, Two>;
Run Code Online (Sandbox Code Playgroud)

RenameByT类型可以分为几个部分。解释是为了例子renameOne

  1. K in keyof U表示 中的所有键U。对于这个例子是one | two | three
  2. as子句从 ts4.1 开始就可以使用。但我不能在 4.4.4 中使用,但可以在 4.6.2 中使用。这是用来根据条件类型重命名Key的 K
  3. K extends keyof T。keyof T 的意思是three | five.
  4. T[K] extends string意思T[K]是字符串。T['three']是字符串,所以返回four,T['five']返回nouse;
  5. 返回类型K extends keyof U,因此T['three']满足所以返回{ four: U['three'] }意味着{ four: boolean}
  6. 其他键返回原点

参考:

https://github.com/microsoft/TypeScript/issues/40833 https://www.typescriptlang.org/docs/handbook/2/mapped-types.html