对象类型接口
定义接口
interface List { id: number; name: string; } interface Result { data: List[] } function render(result: Result) { result.data.forEach((value) => { console.log(value.id, value.name) }) } let result = { data: [ {id: 1, name: 'A'}, {id: 2, name: 'B'} ] } render(result) // 1 "A" // 2 "B" PS: 后端有时候会传来约定之外的字段,ts并不报错。所以只要传入的对象是必要条件就是被允许的: let result = { data: [ {id: 1, name: 'A', sex: 'male'}, {id: 2, name: 'B'} ] } 但是我们直接传入对象字面量,ts就会对额外的字段进行类型检查: render({ data: [ {id: 1, name: 'A', sex: 'male'}, // 提示错误 {id: 2, name: 'B'} ] })
绕过类型检查的方法
第一种方式: 将对象赋值给一个变量 第二种方式是类型断言:as + 对象的类型,明确告诉编译器,对象的类型就是Result,编译器就会绕过类型检查
render({ data: [ {id: 1, name: 'A', sex: 'male'}, // 提示错误 {id: 2, name: 'B'} ] } as Result) PS: 类型断言的另一种不建议用的方法,就是在对象前面加上<Result>,但是在React种容易产生歧义。
第三种方法是使用字符串索引签名,格式如下:
interface List{ id:number; name:string; [x,string]:any; } PS: 该签名的含义是用任意的字符串去索引List,会得到任意的结果,这样List就支持多个属性了。
可选属性(属性+格式)
假设有个新需求,需要判断value中是否有个新字段,如果有,就把它打印出来:
interface List { id: number; name: string; age?: number; } interface Result { data: List[] } function render(result: Result) { result.data.forEach((value) => { console.log(value.id, value.name) if(value.age) { console.log(value.age) } }) } let result = { data: [ {id: 1, name: 'A', sex: 'male'}, {id: 2, name: 'B'} ] } render(result) PS: 在render函数中进行判断,会提示错误,这时我们在List中添加属性age,result会报错,这就需要我们使用可选属性了。
只读属性(readonly + 属性格式)
只读属性不允许修改
interface List { readonly id: number; } function render(result: Result) { result.data.forEach((value) => { value.id ++ // 提示错误 }) }
可索引类型的接口
以上属性的个数是固定的,当我们不确定属性个数时,就要用到可索引类型的接口,常用的有两种: 用数字索引的接口
interface StringArray { [index: number]: string } PS: 含义是用任意的数字去索引StringArray,会得到一个string,这就相当于声明了一个字符串类型的数组。 比如: let chars: StringArray = ['A', 'B']
用字符串索引的接口
interface Names { [x: string]: string } PS: 含义是用任意的字符串索引Names,得到的结果都是string,这样我们就不能并列声明number类型的成员了: interface Names { [x: string]: string y: number // 提示错误 z: string }
这两种索引签名是可以混用的
interface Names { [x: string]: string [z: number]: string } PS: 需要注意的是,数字索引签名的返回值一定要是字符串索引签名返回值的子类型,这是因为js会进行类型转换,将number转成string,这样就能保证类型的兼容性。 比如下面这样就会报错: interface Names { [x: string]: string [z: number]: number // 提示错误 } 但这样就可以: interface Names { [x: string]: any [z: number]: number }
函数类型接口
定义接口
用变量定义函数类型
let add: (x: number, y: number) => number
用接口定义函数类型
interface Add { (x: number, y: number): number }
用类型别名定义函数类型
type Add = (x: number, y: number) => number let add: Add = (a, b) => a + b
混合类型的接口 这种接口既可以定义一个函数,也可以像对象一样拥有属性和方法
interface Lib { (): void version: string doSomething(): void } let lib: Lib = (() => {}) as Lib lib.version = '1.0' lib.doSomething = () => {}
我们可以创造多个lib实例
function getLib() { let lib: Lib = (() => {}) as Lib lib.version = '1.0' lib.doSomething = () => {} return lib } let lib1 = getLib() lib1() lib1.doSomething() let lib2 = getLib()
来源:https://www.cnblogs.com/xfxing/p/12652266.html