Typescript的结构性子类型是根据Javascript代码的典型写法来设计的。 因为Javascript里广泛的使用匿名对象,例如函数表达式和对象字面量,所以使用结构类型系统来描述这些类型比使用名义类型系统更好。
Typescript结构化类型的基本原则是:如果**x**
要兼容**y,**
那么**y**
至少要具有与**x**
相同的属性。
注意:字面量对象兼容的前提是,兼容的值的双方都已经赋值了。并且初始化值的时候,肯定满足对应的类型。
let a: { a: number }
a = { a: 1, b: 2 } // Error
// 不能将类型“{ a: number; b: number; }”分配给类型“{ a: number; }”。
// 对象文字可以只指定已知属性,并且“b”不在类型“{ a: number; }”中。
值初始化之后,再次赋值的时候,开始检查并满足结构化赋值。
let a = {
a: 1
}
let b = {
a: 1,
b: 2
}
a = b // Success
b = a // Error
// 类型 "{ a: number; }" 中缺少属性 "b",但类型 "{ a: number; b: number; }" 中需要该属性。
基础类型的结构化兼容
基础类型的兼容,只需要保证赋值的类型满足对应的就可以。
const a = '123'// a:'123'
对象的结构化兼容
对象的字面量初始化
通过类或者构造函数进行对象的初始化
class A {
x = 0
y = 'name'
}
let a: { x: number } = new A() // Success
函数参数
function A(a: number, b: { a: number }) {
console.log(a, b)
}
A(1, { a: 1, b: 2 }) // Error: 第二个参数没有b这个属性。
function A(a: number, b: { a: number }) {
console.log(a, b)
}
const d = { a: 1, b: 2 }
A(1, d) // Success
函数变量
let x = (a: number) => {
console.log(a)
}
let y = (b: number, s: string) => {
console.log(b, s)
}
x = y // Error
y = x // Success let y: (b: number, s: string) => void
y
赋值给x
,也就是形参多的不可以赋值给形参少的。防止赋值或参数传递变少,变少会影响结果。x
赋值给y
,也就是形参少的,可以赋值给形参多的。参数可以和原来一样或者变少了,变少了不会影响结果,变多只是可能会影响结果。
不建议这样进行结构化兼容。要么就写函数重载。