typescript(ts) 接口类型兼容性 分析
含义: 在ts 中,有两个值,A 和 B, 将B的值赋值给A,如果能完成赋值,则B和A类型兼容
检查原始类型
ts 类型系统在检查普通字面量是严格检查的,是完全匹配的,如果有一点不一样,ts 都会提出错误,原因嘛,个人觉得你既然使用了类型检查,对于普通的原生数据类型肯定是严格检查,有一点都报错
// 例如 type Test = string; // 这一行代码不会报错 const t:Test = '1' // 这一行代码会报错 const t2: Test = 1;
检查对象 —— 鸭式辩型法(结构子类型)
含义: 啥叫作鸭式辩型法? 像鸭子一样走路、游泳和嘎嘎叫的鸟就是鸭子——这就是所谓的“鸭式辩型法”。详细一点的话,问一下自己接口是什么,是一种约定。所以,所谓的“鸭式辩型法”就是去检测这种约定是否遵守而已。
// 举个例子,定义一个用户的接口 interface User { name: string, age?: number, } // 声明一个用户来使用该接口,多了一个属性,会报错,如下图 const u:User = { name: '2343', age: 12, sex: "男" }
注意: 直接使用字面量的形式,ts 是会进行严格的检查,几乎要一模一样。但是大家思考一个问题,如果我们的 u 是从一个函数返回的结果或者是ajax 请求返回的结果,这里面的参数我们不能控制里面有多少,打个比方:我们查询用户信息,我们只要两个数据那name 和 age, 但是后台说返回两个要改业务逻辑,只能返回三个name, sex, age,ts 会 报错么, 告诉你,ts 是不会报错的。如下:
interface User { name: string, age?: number, } let res = { name: '2343', age: 12, sex: "男" } const u:User = res
ts 在对对象这里可谓是用心良苦,让我们在开发中是无感的,既能完成类型检查,又能像js 一样的完成赋值。赋值后,还只能使用你声明的那几个属性。像上面的那个例子,就可以叫做是鸭子辩型法,既然要伪装成一只鸭子,那就伪装的彻底。
类型断言
定义:类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构
语法:<类型>值 或者 值 as类型
interface User { name: string, age?: number, } const u1:User = <User> { name: '2343', age: 12, sex: "男" } const u:User = { name: '2343', age: 12, sex: "男" } as User // 这样写是不会报错的
检查函数
- 接口能够描述JavaScript中对象拥有的各种各样的外形。 除了描述带有属性的普通对象外,接口也可以描述函数类型。
- 为了使用接口表示函数类型,我们需要给接口定义一个调用签名。 它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型
- 简单的说就是,一切无比丝滑,无感的。
场景: 需要一个函数,传入一个数组,我需要求指定条件的和,例如: 求都是奇数或者偶数,或者质数等的和
// 声明条件接口 interface Condition { (n: number): boolean } // 定义一个求和函数, 传入一个回调函数 function sum (arr:number[], cb:Condition){ let rs:number = 0 arr.forEach((n,i) => { if (cb(n)) { rs += n; } }) return rs; } // 如果少穿一个回调函数,直接报错,因为少了一个参数,在js 中也是会报错的 // sum([1,2,34,5,6])
注意: 在ts 中,如果你的是传入的是目标函数(回调函数),回调函数里面的参数是可以少的。但是目标函数里面的返回值,如果是不需要的,你在里面返回时不生效的。
函数总结:
参数:传递给目标函数的参数可以少,但不可以多
返回值:要求返回必须返回;不要求返回,你随意;
彩蛋,接口的readonly
顾名思义,只读属性在创建后不能修改。这里我们通过在属性名前用readonly来指定。
interface Point { readonly x: number; readonly y: number; } let p1: Point = { x: 10, y: 20 }; p1.x = 5; // error!
TypeScript具有ReadonlyArray<T>类型,它与Array<T>相似,只是把所有可变方法去掉了,因此可以确保数组创建后再也不能被修改:
let a: number[] = [1, 2, 3, 4]; let ro: ReadonlyArray<number> = a; ro[0] = 12; // error! ro.push(5); // error! ro.length = 100; // error! a = ro; // error!
我们如果想将它赋值给普通数组,可以使用as断言。
let b = ro as number[];
readonly和const的区别
最简单判断该用readonly还是const的方法是看要把它做为变量使用还是做为一个属性。 做为变量使用的话用const,若做为属性则使用readonly。