您的示例之间存在显着差异。您首先考虑的分配值的类型彼此之间没有关系。我所说的关系是交集,所以值是两种类型的成员。没有同时为string 和number 的值。它只能是string 或number,这就是为什么你不能将string 类型的成员分配给预期number 的地方。
对于产品类型(产品是 js 对象,它是 ts 记录)我们有不同的故事,因为一种类型可以包含所有字段,这些字段也属于另一种类型。
type SmallerT = {
a: string
}
type BiggerT = {
a: string,
b: string
}
BiggerT 是SmallerT 的超集,在任何需要SmallerT 的地方都可以使用BiggerT 代替。在更多的接口概念中,我们可以说BiggetT 实现SmallerT 或扩展SmallerT。
这种行为对于 TS 至关重要,因为所有类型/接口只是产品和联合类型的别名,这意味着具有相同结构的一种类型实际上与另一种类型相同。它的structural typying
type A = { a: string }
type B = { a: string }
类型A 和B 相等,相同,我们可以使用A,其中B 是必需的,或者其他方式。
让我们回到前面的例子,换个方式写:
interface SmallerT {
a: string
}
interface BiggerT extends SmallerT {
b: string
}
上面的类型声明与前一个相同,我们只是使用extend 来连接这两种类型,但结构上没有任何变化,仍然可以在需要SmallerT 的地方分配BiggerT。
考虑下面的树类型定义相等:
type SmallerT = {
a: string
}
type BiggerT = {
a: string,
b: string
}
interface SmallerT {
a: string
}
interface BiggerT extends SmallerT {
b: string
}
type SmallerT = {
a: string
}
type BiggerT = SmallerT & {
b: string
}
类型BiggerT 包含SmallerT 并且可以代替它使用,它满足SmallerT 的所有要求。
我们也可以问TS,我们的BiggerT是否可以分配给SmallerT:
type IsBiggerTAssignableToSmallerT = BiggerT extends SmallerT ? true : false
// evaluates into true for any of definitions presented above
type IsNumberAssignableToString = number extends string ? true : false
// evaluates to false as expected