gpt4 book ai didi

typescript - TypeScript 中扩展接口(interface)和相交接口(interface)的区别?

转载 作者:搜寻专家 更新时间:2023-10-30 20:32:42 24 4
gpt4 key购买 nike

假设定义了以下类型:

interface Shape {
color: string;
}

现在,考虑以下方法来为该类型添加额外的属性:

扩展

interface Square extends Shape {
sideLength: number;
}

十字路口

type Square = Shape & {
sideLength: number;
}

这两种方法有什么区别?

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

最佳答案

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

也许最重要的是当具有相同属性键的成员出现在两种类型中时,处理方式的差异。

考虑:

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

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

上面的 extends 会导致错误,因为派生接口(interface)声明的属性与派生接口(interface)中的 key 相同,但签名不兼容。

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`

Playground Link

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

这是合并行为的常见用法

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 子句,尽管在单独的文件中指定接口(interface)都在全局范围内,并且按名称合并到一个具有两组成员的逻辑接口(interface)声明中。 (对于语法略有不同的模块范围声明也可以这样做)

相比之下,存储在 type 声明中的交集类型是封闭的,不受合并影响。

有很多很多的不同。您可以在 TypeScript 手册中阅读有关这两种构造的更多信息。 InterfacesAdvanced Types部分特别相关。

关于typescript - TypeScript 中扩展接口(interface)和相交接口(interface)的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52681316/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com