TypeScript的核心原则之一是对值所具有的结构进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。
先简单看个例子
interface User {
name: string;
age: number
}
let user:User = {name: 'fufu'} //Error
当我们使用接口定义结构时,如果声明的变量接口不同于接口,那就会报错。这里的不同于指的是必须含有接口定义的属性,不多不少。
interface User {
name: string;
age: number
}
let user:User = {name: 'fufu', age: 20} // ok
可选属性
但是我们时常定义完成后,并不是每次都能够拥有某个属性的,所以我们可以定义一个可选属性
interface User {
name: string;
age?: number
}
let user:User = {name: 'fufu'} // ok
绕开多余属性检查
很多时候,我们只需要满足我们接口定义的属性即可,不在意是不是存在多余的属性,实现的方式有三个:
1. 使用类型断言
interface User {
name: string;
age: number
}
let user:User = {name: 'fufu', age: 20, love: 'love' } as User
2. 添加索引签名
interface User {
name: string;
age: number;
[prop: string]: any
}
let user:User = {name: 'fufu', age: 20, love: 'love' }
3 利用类型兼容性
interface User {
name: string;
}
const getVegetables = ({ name }: User) => {
console.log(name);
return name;
};
const user = { name: "fufu", size: 12 };
getVegetables(user);
上面的函数里面我们要求是需要一个User类型的对象当作参数,但是我们随机定义了一个包含User类型属性的普通对象后,赋值给变量再当作参数传递就通过了校验。
是因为直接将对象字面量传入函数,和先赋给变量再将变量传入函数,这两种检查机制是不一样的,后者是因为类型兼容性。简单地来说:如果 b 要赋值给 a,那要求 b 至少需要与 a 有相同的属性,多了无所谓。
只读属性
有时候,我们只希望某些属性是只读的,不能被随便修改,这个时候我们使用readonly 即可
interface User {
readonly name: string;
}
let user:User = { name: "fufu" };
user.name = 'dandan' //Error
定义函数
接口除了用来定义对象外,还可以用来定义函数。
// 该接口定义了一个函数的参数个数,类型以及返回值。
interface AddFunc {
(num1: number, num2: number): number;
}
let add:AddFunc = (n1:number, n2:number) => n1 + n2
你应该注意到了,实际定义函数的时候,名字是无需和接口中参数名相同的,只需要位置对应即可
偷了一张图片总结:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLzkDN0ADN1IGNwADN5IGMhBTM2QTO1YmY1kDNzEWMiN2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)