接口
我们使用接口来定义对象的类型。接口是对象的状态(属性)和行为(方法)的抽象(描述)
简单理解就是:为我们的代码提供一种约定
我们使用关键字interface来声明接口
interface Person {
name: string;
age: number;
}
let tom: Person = {
name: 'Tom',
age: 25
};
我们定义了一个接口 Person,接着定义了一个变量 tom,它的类型是 Person。这样,我们就约束了 tom 的形状必须和接口 Person 一致。
接口一般首字母大写。(当然挺多人也习惯 I 大写字母开头,用来表示这是一个接口)
设置接口可选|只读
interface Person {
readonly name: string;
age?: number;
}
可选属性,我们最常见的使用情况是,不确定这个参数是否会传,或者存在。
只读属性用于限制只能在对象刚刚创建的时候修改其值。此外 TypeScript 还提供了 ReadonlyArray 类型,它与 Array 相似,只是把所有可变方法去掉了,因此可以确保数组创建后再也不能被修改。
索引签名
有时候我们希望一个接口中除了包含必选和可选属性之外,还允许有其他的任意属性,这时我们可以使用 索引签名 的形式来满足上述要求。
需要注意的是,一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集
interface Person {
name: string;
age?: number;
[prop: string]: any;
}
const p1 = { name: "张麻子" };
const p2 = { name: "树哥", age: 28 };
const p3 = { name: "汤师爷", sex: 1 }
我们规定 以 string 类型的值来索引,索引到的是一个 any 类型的值
接口与类型别名的区别
实际上,在大多数的情况下使用接口类型和类型别名的效果等价,但是在某些特定的场景下这两者还是存在很大区别。
TypeScript 的核心原则之一是对值所具有的结构进行类型检查。而接口的作用就是为这些类型命名和为你的代码或第三方代码定义数据模型。
type(类型别名)会给一个类型起个新名字。type 有时和 interface 很像,但是可以作用于原始值(基本类型),联合类型,元组以及其它任何你需要手写的类型。起别名不会新建一个类型 - 它创建了一个新名字来引用那个类型。给基本类型起别名通常没什么用,尽管可以做为文档的一种形式使用。
接口和类型别名都可以用来描述对象或函数的类型,只是语法不同
type MyTYpe = {
name: string;
say(): void;
}
interface MyInterface {
name: string;
say(): void;
}
都允许扩展
interface 用 extends 来实现扩展
interface MyInterface {
name: string;
say(): void;
}
interface MyInterface2 extends MyInterface {
sex: string;
}
let person:MyInterface2 = {
name:'树哥',
sex:'男',
say(): void {
console.log("hello 啊,树哥!");
}
}
type 使用 & 实现扩展
type MyType = {
name:string;
say(): void;
}
type MyType2 = MyType & {
sex:string;
}
let value: MyType2 = {
name:'树哥',
sex:'男',
say(): void {
console.log("hello 啊,树哥!");
}
}
不同点
type可以声明基本数据类型别名/联合类型/元组等,而interface不行
type UserName = string;
type UserName = string | number;
type Animal = Pig | Dog | Cat;
type List = [string, boolean, number];
interface能够合并声明,而type不行
interface Person {
name: string
}
interface Person {
age: number
}