扩展类型—接口的概念
扩展类型:类型别名、枚举、接口、类、泛型
查阅官方的接口文档、调用一个后台的接口
TypeSript的接口 Interface :用于 约束类、对象、函数等的 契约(标准)
契约(标准)的形式:
- API文档,弱标准:因为开发人员可能写错或者不按这个规范走
- 代码约束,强标准:写错了,编辑器会立即提示你
接口的使用
接口与类型别名还是有区别的,重点是在于 约束类 上。
接口interface和类型别名type都不会出现在编译结果中!!定义接口:
```typescript //关于约束函数 // type Condition = {//这个大括号表示定界符,不再是对象了 // (n:number)=>boolean; // }interface User {name: stringage: number//sayHello:() => void//注意:这里千万不要写函数的实现sayHello():void//也可以写成这种形式}//对比类型别名type, 可以认为除了 约束类 以外,它们的差别很细微type User2={name: string,age: number,sayHello:() => void}
interface Condition {//Condition就是函数 (n: number): boolean }
function sum(numbers: number[], callback: Condition): number { let s = 0; numbers.forEach(n => { if (callback(n)) { s += n; } }); return s; }
const result = sum([3, 4, 5, 7, 11], n => n % 2 !== 0); console.log(result);
<a name="pTGcA"></a>## 接口可以(多)继承```typescriptinterface A {T1: string}interface B extends A {//这里还能这样啊, ..强啊T2: number}interface C extends A, B {//T1: number//这是不允许的, 它不能对A的同名T1成员进行类型更改T3: boolean}let c: C = {T1: 'A_T1',T2: 22,T3: true,}console.log(c);
虽然 类型别名 type 也可以实现类似的组合效果—叫做 交叉类型,使用 & ,但是还是有缺陷,故建议使用接口
type A = {T1: string};type B = {T2: number};type C = {T1: numberT3: boolean} & A & B;let c: C = {T1: 'A_T1',//最终T1是 number&string --> never, 此时赋值什么都会给警告T2: 22,T3: true,}
交叉类型 与 接口继承的区别:
- 接口继承,子接口不能覆盖父接口的成员
- 交叉类型,会把相同成员的类型进行取并集,最终变成never,会报错
readonly修饰符
对象成员名 或 约束类型 前面加上 readonly 即可,所以要区分好readonly修饰的目标是谁!!
一经赋值,不可再次修改
只读修饰符不在编译结果中
变量只读需要用 const ,不要学懵了!
对于readonly数组类型:数组一经赋值,绝对不可更改数组内容了,是浅对比, 但可以直接改变引用(非const下)
如果readonly对象成员名,则成员不可更改引用,但是可以修改具体内容
let arr: readonly number[] = [1,2,3,4];//arr[0] = 3;//报错//arr.splice//已经报错了let arr2: ReadonlyArray<number> = [1,3,5,6];//interface User {readonly name: stringage: numbersayHello(): voidreadonly arr: readonly string[] //完全只读,浅对比}
类型兼容性
如果A<-B,能完成赋值,则B和A类型兼容
带着 欣赏的角度 看看TS是怎么做类型兼容的
类型断言
用法:1. 数据 as 类型 2. <类型>数据 但写法2,在react中并不推荐,容易和组件搞混
也不会出现在编译结果中
鸭子辨型法(子结构辨型法)
目标类型需要某一些特征,赋值的类型只要能满足该特征即可
interface Duck{sound: '嘎嘎嘎'//这是字面量swim():void}let person = {name:'伪装成鸭子的人',age:11,// sound: '嘎嘎嘎'//这里推断出的是字符串,因为没进行类型约束,但是我们希望把它断言成字面量, 怎么办呢?sound: '嘎嘎嘎111' as '嘎嘎嘎',swim(){console.log(this.name, '正在游泳,并且发出了 ', this.sound, '的声音');}}let duck:Duck = person;//你看, 这样就能完成赋值
例如:假设有个函数用于得到服务器的某个接口的返回结果,是一个用户对象,我不需要所有的字段,我只想用某一小部分字段,怎么办呢
function getUserInfo() {return {loginId: '234',nickName: 'wjw',gender: "男" as '男',age: 22,power: 'strong',};}let u = getUserInfo();interface ResponseUser {loginId: string,nickName: string,gender: "男" | "女"}let user: ResponseUser = u;//这里不能直接用字面量赋值过来,否则就报错
当直接使用对象字面量赋值的时候,将使用更加严格的判断,防止隐患,TS真是细啊!
