当我有一个具有两个作为函数的属性的类型A,然后定义一个类型B与它具有与A相同的函数属性的新类型时,该类型B是类型A的交集类型,那么TS如何理解这一点?如果使用接口完成此操作,将是一个错误,因为接口B将具有b的调用签名,而该调用签名将与接口A的调用签名不兼容。
type A = {
a(x: number): string,
b(x: number): string
}
type B = A & {
a(x: string): string,
b(x: number): string
}
const b: B = {
a: (x: string | number) => x,
b: (x: number) => x
}
在const变量b的两个属性上均显示错误,但在实际的类型定义上均未显示。那么什么是B类型变量的有效声明?
TypeScript将函数类型的交集视为函数重载。因此,相同类型的每个其他调用签名(或者,在上述情况下,同一个名称的每个其他方法声明)在该函数(或方法)的重载列表中充当附加的调用签名。从文档中并不清楚。(大部分已过时的)TypeScript规范文档中有一个部分说明了有关可调用类型的交集:
的交点型的表观成员我如下确定...当一个或多个组成类型的我有一个呼叫签名小号,我具有明显的呼叫签名小号。签名按I中组成类型的顺序排序,作为每种组成类型的签名的串联。
基本上,这意味着函数的交集的行为类似于具有交集中每个调用签名的函数,其顺序与交集相同。具有调用签名的有序列表的函数至少在TypeScript中是“重载函数”的含义。
所以,那个路口是不是一个错误,而是指定您希望的方式B
有一个a
方法有两个不同的签名,并且b
有两个相同的特征,这样的方法:
interface IB {
a(x: number): string;
a(x: string): string;
b(x: number): string;
b(x: number): string;
}
有点奇怪,尤其是对于b
,但不是错误。
之所以不能A
作为接口使用,B extends A
是因为extends
它与交集无法完全相同。因为B extends A
根本不允许您声明不兼容的属性。即使对于非功能部件也是如此。interface C {x: number | string}
并且interface D extends C {x: string | boolean}
由于string | boolean
无法分配给而无法正常工作number | string
。这是不一样的交集(number | string) & (string | boolean)
这仅仅是string
。
无论如何,您在b
变量中出现了错误。为什么?好吧,因为您的a
和b
方法都没有返回正确的类型。你a
回来string | number
和你b
回来number
。但是所有的方法B
都应该返回string
。
让我们修复一下:
const b: B = {
a: (x: string | number) => String(x),
b: (x: number) => String(x)
} // no error now
现在看起来还好。好吧,希望能有所帮助;祝好运!
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句