在 TypeScript 中扩展多个接口

在 TypeScript 中扩展多个接口

Extend multiple interfaces in TypeScript

使用extends关键字在 TypeScript 中扩展多个接口,例如
interface Developer extends Person, Employee {}. 关键字允许我们从extends指定类型复制成员并将新成员添加到最终接口。

索引.ts
interface Person { name: string; } interface Employee { id: number; salary: number; } interface Developer extends Person, Employee { language: string; } const dev: Developer = { id: 1, name: 'Tom', salary: 100, language: 'TypeScript', };

extends
关键字消除了必须在多个地方重复其他类型的成员的需要,并向代码的读者显示了接口之间的关系

您可以通过用逗号分隔接口来根据需要从任意多个接口进行扩展。

您不需要在最终接口中添加任何新成员,可以使用extends关键字简单地组合接口。

索引.ts
interface Person { name: string; } interface Employee { id: number; salary: number; } // 👇️ Combine the Person and Employee interfaces interface Developer extends Person, Employee {} // 👇️ Alternatively use intersection type type Developer2 = Person & Employee; const dev: Developer = { id: 1, name: 'Tom', salary: 100, };

上面的示例显示了如何在不向它们添加新属性的情况下组合两个或多个接口。

如果您需要覆盖您扩展的接口之一的属性,您可以使用Omit实用程序类型。

索引.ts
interface Person { name: string; } interface Employee { id: number; salary: number; } // for multiple use - Omit<Employee, 'id' | 'salary'> interface Developer extends Person, Omit<Employee, 'id'> { id: string; // 👈️ override type of id } const dev: Developer = { id: 'dev-1', name: 'Tom', salary: 100, };

Omit
实用程序类型通过从提供的类型中选取属性并删除指定的键来构造一个新类型

在示例中,我们在id从类型扩展时从类型中删除了属性,因此我们可以覆盖它的类型。 Employee

如果我们没有删除该属性并尝试在
Developer接口中指定不同的类型,我们就会得到一个错误。

索引.ts
interface Person { name: string; } interface Employee { id: number; salary: number; } // ⛔️ Error: Interface 'Developer' incorrectly extends interface 'Employee'. // Types of property 'id' are incompatible. // Type 'string' is not assignable to type 'number'.ts(2430) interface Developer extends Person, Employee { id: string; // 👈️ override type of id }
TypeScript 告诉我们不能从接口扩展并使用具有不同的不兼容类型的相同属性名称。

解决这个问题的最好方法是在从接口扩展时删除类型并在新接口中覆盖它。

在扩展时,您可以使用字符串文字的
并集
来省略类型的多个属性。

索引.ts
interface Person { name: string; } interface Employee { id: number; salary: number; tasks: string[]; } interface Developer extends Person, Omit<Employee, 'id' | 'salary'> { id: string; // 👈️ override type of property salary: string; // 👈️ override type of property language: string; } const dev: Developer = { id: 'dev-1', name: 'Tom', salary: '100 K', language: 'TypeScript', tasks: ['develop', 'test'], };

要将多个属性传递给Omit实用程序类型,请使用管道分隔属性|

扩展时可以使用相同的方法从类型中删除某些属性——省略属性并且不重新定义它们。

请注意,从接口扩展时,您可以为相同的属性名称提供更窄的类型。

索引.ts
interface Person { name: string; } interface Employee { id: number | string; // 👈️ number OR string (wide) salary: number; } interface Developer extends Person, Employee { id: string; // 👈️ only string (narrow) language: string; } const dev: Developer = { id: 'dev-50', // 👈️ can only be string now name: 'Tom', salary: 100, language: 'TypeScript', };

接口中的id属性Employee有一个类型numberor
string,但是当从接口扩展时,我们指定了一个更窄的类型string

接口中的id属性Developer只能是类型string

允许使用更具体的类型覆盖属性的类型,但是,您不能提供不兼容的类型。如果需要这样做,则必须使用Omit实用程序类型来删除特定属性并覆盖其类型。

扩展接口的主要好处是:

  1. 减少重复,因为我们不必在接口之间复制属性。
  2. 向我们代码的读者发出信号,表明这两种类型之间存在关系。

发表评论