接口的定义
接口可以约束函数、对象、类的结构和类型,接口使用interface
去定义
interface Myinterface {
//...
}
如何使用
如果后端返回一个列表,如何判断后端返回来的结果符合前端定义的接口呢?
// 定义一个List接口
interface List {
id: number;
name: string;
}
// 使用List接口定义Result接口
interface Result {
data: List[]
}
// render接收后端返回来的result,result要满足Result接口
function render(result: Result) {
result.data.forEach((value) => {
console.log(value.id, value.name)
})
}
// 这个result满足Result接口
let result = {
data: [
{id: 1, name: 'A', sex: 'male'},
{id: 2, name: 'B', age: 10}
]
}
render(result)
如果result
是下面的值,也满足Result接口,只要result的属性满足接口的必要条件就可以通过ts的类型检查,就是说result中list的属性除了要满足Result中定义的属性,还可以添加更多的属性,就像下面的代码,添加sex: 'male'
属性
let result = {
data: [
{id: 1, name: 'A', sex: 'male'},
{id: 2, name: 'B'}
]
}
注意如果直接把上面对象字面量作为参数传递给render
函数是会报错的
有三种办法解决上面的报错警告:
- 把字面量对象赋值给一个变量,把变量传给render函数
let result = {
data: [
{id: 1, name: 'A', sex: 'male'},
{id: 2, name: 'B'}
]
}
render(result)
- 使用类型断言(as),明确告诉编译器这是一个满足Result接口的对象
render({
data: [
{id: 1, name: 'A', sex: 'male'},
{id: 2, name: 'B'}
]
} as Result)
// 不建议使用下面这种,会在React中产生歧义
render(<Result>{
data: [
{id: 1, name: 'A', sex: 'male'},
{id: 2, name: 'B'}
]
})
- 使用字符串索引签名,使用任意的string索引List,得到任意的结果
interface List {
id: number;
name: string;
[x: string]: any;
}
意思就是使用任意的string索引List,得到任意的结果,这样list就可以添加任意的属性来
如果render添加一个逻辑判断list是否有age
属性
function render(result: Result) {
result.data.forEach((value) => {
console.log(value.id, value.name)
if (value.age) {
console.log(value.age)
}
})
}
那么接口List应该添加一个可选属性age?
interface List {
id: number;
name: string;
age?: number;
}
如果给id加一个readonly, 那么id是只读的,不可以修改
interface List {
readonly id: number;
name: string;
age?: number;
}
// 修改result里面list的id就会报错
不确定接口属性个数
如果不确定接口属性的个数,就可以使用有索引属性的接口,既可以用数字,也可以用字符串去索引
- 数字索引
interface StringArray {
[index: number]: string
}
let chars: StringArray = ['a', 'b']
意思是用任意的数字去索引StringArray
得到字符串,相当于定义一个字符串类型的数组
- 字符串索引
interface Names {
[x: string]: string;
// y: number; 不能在字符串索引结果为字符串的接口后面加类型为number的属性,string的话就没问题
[z: number]: string;
}
用任意的字符串去索引Names
,得到的结果是字符串,但是不能在后面去声明一个number类型的属性y: number
,因为两种索引签名是可以混用的,如果在后面加上[z: number]: string
,那么既可以用字符串去索引Names也可以用数字去索引Names
,注意数字索引的返回值一定要是字符串索引返回值的子类型,因为ts编译时会进行类型转换,将number
转换成string
,这样就能保持js的兼容性。
interface Names {
[x: string]: string;
[z: number]: number; // number类型不是string的子类型,会报错
}
interface Names {
[x: string]: any;
[z: number]: number; // number类型是any的子类型,可以通过
}