TypeScript中扩展和相交接口之间的区别? [英] Difference between extending and intersecting interfaces in TypeScript?

查看:75
本文介绍了TypeScript中扩展和相交接口之间的区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设定义了以下类型:

interface Shape {
  color: string;
}

现在,考虑使用以下方法向此类型添加其他属性:

Now, consider the following ways to add additional properties to this type:

扩展

interface Square extends Shape {
  sideLength: number;
}

路口

type Square = Shape & {
  sideLength: number;
}

两种方法之间有什么区别?

What is the difference between both approaches?

出于完整性和好奇心的考虑,还有其他方法可以产生可比的结果吗?

And, for sake of completeness and out of curiosity, are there other ways to yield comparable results?

推荐答案

是的,在您的方案中可能存在或可能不存在差异.

Yes there are differences which may or may not be relevant in your scenario.

也许最重要的是,当两种类型的成员具有相同的属性键时,它们在处理方式上的差异.

Perhaps the most significant is the difference in how members with the same property key are handled when present in both types.

考虑:

interface NumberToStringConverter {
  convert: (value: number) => string;
}

interface BidirectionalStringNumberConverter extends NumberToStringConverter {
  convert: (value: string) => number;
}

上面的extends会导致错误,因为派生接口声明的属性与派生接口中的键具有相同的键,但签名不兼容.

The extends above results in an error because the derriving interface declares a property with the same key as one in the derived interface but with an incompatible signature.

error TS2430: Interface 'BidirectionalStringNumberConverter' incorrectly extends interface 'NumberToStringConverter'.

  Types of property 'convert' are incompatible.
      Type '(value: string) => number' is not assignable to type '(value: number) => string'.
          Types of parameters 'value' and 'value' are incompatible.
              Type 'number' is not assignable to type 'string'.

但是,如果我们使用交叉点类型

However, if we employ intersection types

interface NumberToStringConverter {
  convert: (value: number) => string;
}

type BidirectionalStringNumberConverter = NumberToStringConverter & {
  convert: (value: string) => number;
}

没有任何错误并进一步给出

There is no error whatsoever and further given

declare const converter: BidirectionalStringNumberConverter;

const s: string = converter.convert(0); // `convert`'s call signature comes from `NumberToStringConverter`

const n: number = converter.convert('a'); // `convert`'s call signature comes from `BidirectionalStringNumberConverter`



// And this is a good thing indeed as a value conforming to the type is easily conceived
const converter: BidirectionalStringNumberConverter = {
    convert: (value: string | number) => {
        return (typeof value === 'string' ? Number(value) : String(value)) as string & number; // type assertion is an unfortunately necessary hack.
    }
}

游乐场链接

这导致另一个有趣的区别,interface声明是开放式的.新成员可以添加到任何地方,因为在同一声明空间中多个具有相同名称的interface声明被合并.

This leads to another interesting difference, interface declarations are open ended. New members can be added anywhere because multiple interface declarations with same name in the same declaration space are merged.

这是合并行为的常见用法

Here is a common use for merging behavior

lib.d.ts

interface Array<T> {
  // map, filter, etc.
}

array-flat-map-polyfill.ts

interface Array<T> {
  flatMap<R>(f: (x: T) => R[]): R[];
}

if (typeof Array.prototype.flatMap !== 'function') {
  Array.prototype.flatMap = function (f) { 
    // Implementation simplified for exposition. 
    return this.map(f).reduce((xs, ys) => [...xs, ...ys], []);
  }
}

请注意如何不存在extends子句,尽管接口在单独的文件中指定,但它们都位于全局范围内,并且按名称合并为具有两组成员的单个逻辑接口声明. (对于语法范围稍有不同的模块范围的声明,也可以这样做)

Notice how no extends clause is present, although specified in separate files the interfaces are both in the global scope and are merged by name into a single logical interface declaration that has both sets of members. (the same can be done for module scoped declarations with slightly different syntax)

相反,存储在type声明中的相交类型是封闭的,无需合并.

By contrast, intersection types, as stored in a type declaration, are closed, not subject to merging.

有很多很多不同之处.您可以在TypeScript手册中阅读有关这两种构造的更多信息. 接口

There are many, many differences. You can read more about both constructs in the TypeScript Handbook. The Interfaces and Advanced Types section are particularly relevant.

这篇关于TypeScript中扩展和相交接口之间的区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆