TypeScript 从现有接口创建新接口并更改所有属性的类型

Posted

技术标签:

【中文标题】TypeScript 从现有接口创建新接口并更改所有属性的类型【英文标题】:TypeScript create new interface from existing interface and change type of all properties 【发布时间】:2021-11-18 04:33:55 【问题描述】:
interface UserFlags 
  isDev: boolean;
  isAdmin: boolean;
  isMod: boolean;


const flagPositions: FlagPositions<UserFlags> = 
  isDev: 0,
  isAdmin: 1,
  isMod: 2,
;

您将如何实现FlagPositions,以便将1 个泛型参数传递给 [name: string]: boolean 类型的接口,并要求接口的所有属性都存在于新接口中,但类型为number

我使用keyof 尝试了各种方法,但都没有奏效。

编辑:发布后我得到了这个工作,但我希望它是一个界面

type FlagPositions<F> = 
  [K in keyof Required<F>]: number;
;

【问题讨论】:

【参考方案1】:

您希望FlagPositions&lt;T&gt; 成为mapped type,其键与keyof T 相同,但其值为number。你可以这样写:

type FlagPositions<T> =  [K in keyof T]: number ;

并验证它是否如您所愿:

const flagPositions: FlagPositions<UserFlags> = 
    isDev: 0,
    isAdmin: 1,
    isMod: 2,
;

请注意,constrain T[name: string]: booleanRecord&lt;keyof T, boolean&gt; 不是必须的,但您可以根据需要这样做:

type FlagPositions<T extends Record<keyof T, boolean>> =
     [K in keyof T]: number ;


declare const oops: FlagPositions< a: number >; // error!
// ---------------------------->  ~~~~~~~~~~~~~
//   Types of property 'a' are incompatible.

您不能将FlagPositions&lt;T&gt; 设为interface,因为接口需要在编译时知道键,而T 是通用的并且可以具有各种键。但是,一旦您拥有具有已知键的 FlagPositions&lt;UserFlags&gt; 类型(它们是 isDevisAdminisMod),那么您可以创建一个 interface 扩展 that: p>

interface UserFlagPositions extends FlagPositions<UserFlags>  

const u: UserFlagPositions = 
    isDev: 2,
    isAdmin: 1,
    isMod: 0

Playground link to code

【讨论】:

非常感谢。可以转成界面吗? 你可以写interface UserFlagPositions extends FlagPositions&lt;UserFlags&gt; 。但是您正在更改问题的范围,任何进一步的范围更改可能都需要单独发布 对不起,我不清楚。一个界面是我最初想要的,但是因为它可以工作,所以一切都很好

以上是关于TypeScript 从现有接口创建新接口并更改所有属性的类型的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript 中的类和接口

如何创建具有索引签名和不同类型的固定属性的 TypeScript 接口?

是否可以从 TypeScript 接口创建一个“空”对象?

Typescript 基于接口从另一个对象创建一个对象

在模块内合并 TypeScript 接口

从0开始的TypeScriptの四:接口Interfaces · 上