interface
#typescript
另外可参考 2. type 和 interface 的区别
目录
- 1. 基本概念
- 2. 可选属性
- 3. 只读属性
- 4. 函数类型接口
- 5. 类类型接口
- 6. 继承接口
- 7. 混合类型接口
- 8. 索引签名
- 9. 接口合并
- 10. 实用技巧
- 11. 最佳实践
- 12. 注意事项
- 13. 高级用法
1. 基本概念
Interface 是 TypeScript 中一个核心概念,用于定义对象的类型契约。
- 它描述了对象应该具有的属性和方法的结构。
1.1. 基本语法
interface Person {
name: string;
age: number;
}
// 使用接口
const person: Person = {
name: "张三",
age: 25
}
2. 可选属性
使用 ?
表示属性是可选的:
interface Config {
color?: string;
width?: number;
}
// 以下都是合法的
const config1: Config = { color: "red" };
const config2: Config = { width: 100 };
const config3: Config = {};
3. 只读属性
使用 readonly
修饰符使属性只读:
interface Point {
readonly x: number;
readonly y: number;
}
const p1: Point = { x: 10, y: 20 };
// p1.x = 5; // 错误!x 是只读的
4. 函数类型接口
接口也可以描述函数类型:
interface SearchFunc {
(source: string, subString: string): boolean;
}
const mySearch: SearchFunc = function(src: string, sub: string): boolean {
return src.search(sub) > -1;
}
5. 类类型接口
接口可以强制类遵循特定的契约:
interface ClockInterface {
currentTime: Date;
setTime(d: Date): void;
}
class Clock implements ClockInterface {
currentTime: Date = new Date();
setTime(d: Date) {
this.currentTime = d;
}
}
6. 继承接口
接口可以相互继承:自己继承自己
interface Shape {
color: string;
}
interface Square extends Shape {
sideLength: number;
}
const square: Square = {
color: "blue",
sideLength: 10
}
7. 混合类型接口
一个对象可以同时作为函数和对象使用:
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
let counter = function(start: number) {} as Counter;
counter.interval = 123;
counter.reset = function() {};
return counter;
}
8. 索引签名
可以描述可以额外拥有其他属性的对象:
interface StringArray {
[index: number]: string;
}
interface Dictionary {
[key: string]: any;
}
const myArray: StringArray = ["Bob", "Fred"];
const myDict: Dictionary = {
name: "张三",
age: 25,
isStudent: true
};
9. 接口合并
TypeScript 允许你声明多个同名接口,它们会自动合并:
interface Box {
height: number;
}
interface Box {
width: number;
}
// 等同于:
// interface Box {
// height: number;
// width: number;
// }
const box: Box = { height: 5, width: 6 };
10. 实用技巧
10.1. 接口继承类:同时使用 extends 和 implements
class Control {
private state: any;
}
interface SelectableControl extends Control {
select(): void;
}
class Button extends Control implements SelectableControl {
select() {}
}
10.2. ==可选方法==:和可选属性一样
interface EventListener {
onClick?(): void;
onMouseOver?(): void;
}
10.3. readonly 数组
interface ReadonlyStringArray {
readonly [index: number]: string;
}
11. 最佳实践
11.1. 命名约定:
- 接口名通常以大写字母
I
开头(虽然不是必须的) - 使用
PascalCase
命名方式
11.2. 接口分离原则:
- 保持接口小而精确
- 一个接口只负责一个功能域
// 好的实践
interface IUser {
id: number;
name: string;
}
interface IUserActions {
updateName(newName: string): void;
deleteUser(): void;
}
// 而不是
interface IUserWithActions {
id: number;
name: string;
updateName(newName: string): void;
deleteUser(): void;
}
11.3. 使用泛型接口:
interface IResponse<T> {
data: T;
status: number;
message: string;
}
// 使用
interface IUser {
name: string;
email: string;
}
const response: IResponse<IUser> = {
data: { name: "张三", email: "zhangsan@example.com" },
status: 200,
message: "success"
};
==范型接口,很有用的==
12. 注意事项
-
接口不会生成 JavaScript 代码,它们只在编译时用于类型检查。
-
接口可以描述 JavaScript 中不存在的类型,如联合类型:
interface Result {
success: boolean;
error?: string | Error;
}
- 实现接口时,必须严格遵守接口定义的结构:
interface Vehicle {
brand: string;
model: string;
}
// 错误:缺少必需的属性
const car: Vehicle = {
brand: "Toyota"
}; // 类型错误!
// 正确
const car: Vehicle = {
brand: "Toyota",
model: "Camry"
};
13. 高级用法
13.1. 映射类型与接口
interface Person {
name: string;
age: number;
}
// 创建所有属性可选的新接口
type PartialPerson = Partial<Person>;
// 创建所有属性只读的新接口
type ReadonlyPerson = Readonly<Person>;
13.2. 条件类型与接口
interface Animal {
live(): void;
}
interface Dog extends Animal {
woof(): void;
}
type Example1 = Dog extends Animal ? number : string; // type Example1 = number