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 // Successb = a // Error// 类型 "{ a: number; }" 中缺少属性 "b",但类型 "{ a: number; b: number; }" 中需要该属性。
基础类型的结构化兼容
基础类型的兼容,只需要保证赋值的类型满足对应的就可以。
const a = '123'// a:'123'
对象的结构化兼容
对象的字面量初始化
通过类或者构造函数进行对象的初始化
class A {x = 0y = '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 // Errory = x // Success let y: (b: number, s: string) => void
y赋值给x,也就是形参多的不可以赋值给形参少的。防止赋值或参数传递变少,变少会影响结果。x赋值给y,也就是形参少的,可以赋值给形参多的。参数可以和原来一样或者变少了,变少了不会影响结果,变多只是可能会影响结果。
不建议这样进行结构化兼容。要么就写函数重载。
