通常使用接口(Interface)来定义对象的类型
interface IUser {
name: string;
age: number;
}
// 正常
let user: IUser = { name: "张三", age: 22 };
// 异常
let user1: IUser = { name: "张三" };
let user2: IUser = { name: "张三", age: "22" };
let user3: IUser = { name: "张三", age: 22, phone: 111 };
可选属性
带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个?
符号。定义的属性可以不用实现
interface IUser {
name: string;
age?: number;
eat?(): void;
run?: () => void;
getScore?: () => { score: number }
}
// 正常
let user: IUser = { name: "张三", age: 22 };
let user2: IUser = { name: "张三", run() { console.log("跑步") } };
let user3: IUser = { name: "张三", getScore: () => { return { score: 0 } } };
let user4: IUser = { name: "张三", getScore() { return { score: 0 } } };
// 异常
let user5: IUser = { age: 22 };
只读属性
只读属性只能在对象刚刚创建的时候修改其值。 在属性名前用readonly
来指定只读属性
interface Point {
x: number;
readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
// 正常
p1.x = 5;
// 异常
p1.y = 5;
可索引接口
例1:
interface IPerson {
[propName: string]: number;
}
// 正常
const p: IPerson = {
age: 23,
phone: 123333,
1: 12, //不知道为什么没报错
};
// 异常
const p2: IPerson = {
age: "23",
phone: true,
1: "a",
};
例2:
// 对数组的约束
interface IUserArr {
[index: number]: string;
}
// 正常
let arr: IUserArr = ["a", "b", "c"];
// 异常
let arr2: IUserArr = [1, true];
// 对对象的约束
interface IUserObj {
[index: string]: number;
}
// 正常
let arr3: IUserObj = { age: 23, phone: 12333 };
// 异常
let arr4: IUserObj = { name: "张三" };
函数类型接口
方式1:不推荐
const add: {
(n1: number, n2: number): number;
} = (n1: number, n2: number): number => {
return n1 + n2;
};
console.log("add(10, 20):", add(10, 20)); // 30
方式2:
interface IAdd {
(n1: number, n2: number): number;
}
const add2: IAdd = (n1: number, n2: number): number => {
return n1 + n2;
};
console.log("add2(10, 20):", add2(10, 20)); // 30
interface IPerson {
eat: () => void;
run(): void;
weight: () => number;
height: number;
}
let p: IPerson = {
eat: () => {
console.log(`吃饭`);
},
run(): void {
console.log(`跑步`);
},
weight: () => 10,
height: 170,
};
p.eat(); //吃饭
p.run(); //跑步
console.log(p.weight()); //10
let weight2: any = p.weight;
console.log(weight2()); //10
console.log(p.height); //170
当然,除非特殊情况,函数类型还是推荐使用类型别名(type)的方式来定义
type TAdd = (n1: number, n2: number) => number;
const add2: TAdd = (n1: number, n2: number): number => {
return n1 + n2;
};
console.log("add2(10, 20):", add2(10, 20)); // 30
接口继承接口(extends)
继承的每个接口里的内容都需要满足
继承单个接口
interface IPerson1 {
name: string;
}
interface IPerson extends IPerson1 {
age: number;
}
const p: IPerson = {
name: "张三",
age: 18,
};
console.log(p);
继承多个接口
interface IPerson1 {
name: string;
}
interface IPerson2 {
isMan: boolean;
}
interface IPerson extends IPerson1, IPerson2 {
age: number;
}
const p: IPerson = {
name: "张三",
age: 18,
isMan: true,
};
console.log(p);
继承相同接口
interface Foo {
name: string;
}
interface Foo {
age: number;
}
//正常。 name和age都需要定义
const foo: Foo = {
name: "chenyq",
age: 18,
};
// 异常。
const foo2: Foo = {
name: "chenyq",
};