当前位置: 首页 > 知识库问答 >
问题:

TypeScript中扩展接口和相交接口的区别?

荣俊杰
2023-03-14

假设定义了以下类型:

interface Shape {
  color: string;
}

现在,考虑以下方法来向该类型添加附加属性:

扩大

interface Square extends Shape {
  sideLength: number;
}

交叉口

type Square = Shape & {
  sideLength: number;
}

这两种方法有什么区别?

而且,为了完整性和好奇心,还有其他方法可以产生类似的结果吗?

共有1个答案

丌官浩旷
2023-03-14

是的,有些差异可能与您的场景相关,也可能无关。

也许最重要的是,当两种类型中都存在具有相同属性键的成员时,它们的处理方式有所不同。

考虑:

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

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

上面的扩展会导致错误,因为derriving接口声明了一个属性,该属性的键与派生接口中的键相同,但签名不兼容。

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'.

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

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

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

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

// 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.
    }
}

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`

游乐场链接

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

下面是合并行为的常见用法

自由党。d、 ts

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

数组平面映射多边形填充。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子句,尽管在单独的文件中指定了接口,但这些接口都在全局范围内,并按名称合并到一个包含两组成员的逻辑接口声明中。(对于语法稍有不同的模块范围声明也可以这样做)

相反,存储在类型声明中的交叉口类型是关闭的,不需要合并。

有很多很多的不同。您可以在TypeScript手册中阅读有关这两种构造的更多信息。接口和高级类型部分特别相关。

 类似资料:
  • 我需要为对后端服务器的HTTP请求创建某种类型(使用Angular 2),例如:}, 我应该用什么来构建这些模型?谢谢!

  • 为什么它这样做,它有一个更好的做法?在sub接口中实现方法有什么区别吗?

  • 有人知道如何扩展dropwizard界面吗?现在它只有所需的选项,但我需要为anooted方法添加权限。 例如: 我有一个用户管理员和一个普通用户。两者都可以进行身份验证并到达我的@auth带注释的资源。但我想允许一些(不是全部)http方法请求只为管理员和普通用户删除。如何在资源之外执行此操作?类似的东西

  • 主要内容:org.springframework.context.ApplicationContextInitializer,org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor,org.springframework.beans.factory.config.BeanFactoryPostProcessor,,,,,,,,,,,,1.可扩展的接口启动调用顺序图 ApplicationConte

  • 主要内容:org.springframework.context.ApplicationContextInitializer,org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor,org.springframework.beans.factory.config.BeanFactoryPostProcessor,,,,,,,,,,,,1.可扩展的接口启动调用顺序图 ApplicationConte

  • 主要内容:TypeScript,JavaScript,联合类型和接口,TypeScript,JavaScript,接口和数组,实例,实例,TypeScript,接口继承,TypeScript,JavaScript,TypeScript,JavaScript接口是一系列抽象方法的声明,是一些方法特征的集合,这些方法都应该是抽象的,需要由具体的类去实现,然后第三方就可以通过这组抽象方法调用,让具体的类执行具体的方法。 TypeScript 接口定义如下: 实例 以下实例中,我们定义了一个接口 IPe