类型兼容性
两种类型系统 1 structural type system(结构化类型系统) 2 nominal type system(标明类型系统)
ts采用的是结构化类型系统 也叫做duck typing(鸭子类型) 类型检查关注的是值所具有的状态.也就是说,在结构类型系统中 如果是两个对象具有相同的形状,则认为他们属于同一类型
class point{x:number;y:number}
class point2d{x:number;y:number}
const p:point=new point2d()
解释:
point和point2d 是两个名称不同的类
变量p的类型被现实标注为point类型 但是 它的值 却是point2d的实例 并且没有类型错误
因为ts是结构化类型系统 只检查point和point2d的结构是否相同(相同 都具有x和y两个属性,属性类型也相同).
但是 如果在 nominal type system中 (例如 c# java等) 他们是不同的类 类型无法兼容
对象之间的类型兼容性
注意:在结构化类型系统中,如果两个对象具有相同的形状,纳认为他们属于同一类型 这种说法并不准确
更准确的说法: 对于对象类型来说 y的成员至少与x相同 则x兼容y(成员多的可以赋值给少的)
class point{x:number;y:number}
class point2d{x:number;y:number;z:number}
const p:point=new point2d()
解释:
point2d的成员至少与point相同 则point兼容point3d
所以 成员多的point2d可以赋值给成员少的point
接口之间的类型兼容性
除了 class外 ts的其他类型也存在相互兼容的情况 包括: 接口兼容性 函数兼容性等
接口之间的兼容性 类似与class 并且 class和interface 之间也可以兼容
interface point {x:number;y:number}
interface point2{x:number;y:number}
let p1:point
let p2:point2=p1
interface point3{x:number;y:number;z:number}
let p3:point3
p2=p3
class point3{x:number;y:number;z:number}
let p3:point2=new point3()
函数之间的类型兼容性
函数之间兼容性比较复杂 需要考虑 参数个数 参数类型 返回值类型
参数个数 :
参数多的兼容参数少的(或者说 参数少的可以赋值给多的)
type f1=(a:number)=>void
type f2=(a:number,b:number)=>void
let f1:f1
let f2:f2=f1! //'!' 后缀断言运算符可以用于断言操作对象为非null和非undefined,即排除这两种类型的检查。代码编译转化后将去除该断言符。 因为f1这时只是给定义了类型 并没有赋值(值为undefined) 如果不用'!' 则会报错 在赋值前使用了变量“f1”。ts(2454)
const arr=['a','b','c']
arr.foreach(()=>{})
arr.foreach((item)=>{})
解释:
参数少的可以赋值给参数多的,所以 f1可以赋值给f2
数组foreach方法的第一个参数是回调函数,改实例中类型为:(value:rstring,index:number,array:string:[])=>void)
在js中省略用不到的函数参数实际上是很常见的,这样的使用方式 促成了ts中函数类型之间的兼容性
丙炔因为回调函数是有类型的,所以ts会自动推导出 参数 item index array的类型
参数类型:
相同位置的参数类型要相同(原始类型)或兼容(对象类型)
type f1=(a:number)=>string
type f2=(a:number)=>string
let f1:f1
let f2:f2=f1!
复杂的参数类型:
interface point2d{x:number;y:number}
interface point3d{x:number;y:number;z:number}
type f2={p: point2d}=>void
type f3=(p:point3d)=>void
let f2:f2
let f3:f3=f2!
f3=f2!
解释:
注意 此处接口兼容冲突
技巧:将对象拆开 把每个属性看做一个个参数, 则参数少的(f2)可赋值给参数多的(f3)
返回值类型:
只关注返回值类型本身即可
type f5=()=>shring
type f6=()=>string
let f5:f5
let f6:f6=f5!
type f7=()=>{name:string}
type f8=()=>{name:string;age:number}
let f7:f7
let f8:f8
f7=f8!
解释:
如果返回值类型是原始类型 此时两个类型要相同 比如 左侧类型f5和f6
如果返回值类型是对象类型 此时成员多的可以赋值给成员少的 如比 f7和f8
发表评论