一、什么是接口?
用于描述一个对象的结构。
typescript
// 定义一个名为 User 的接口
interface User {
id: number;
name: string;
email: string;
}
function printUserInfo(user: User) {
console.log(`ID: ${user.id}, Name: ${user.name}, Email: ${user.email}`);
}
const myUser: User = {
id: 1,
name: 'Alice',
email: 'alice@example.com',
};
printUserInfo(myUser); // OK
const invalidUser: User = {
id: 2,
username: 'Bob', // 属性名不匹配 编译时错误
// 缺少 name,email 属性
};
二、接口的丰富特性
1. 可选属性(Optional Properties)
有时,对象的某些属性不是必需的。我们可以使用 ?
来标记它们。
typescript
interface UserProfile {
id: number;
username: string;
bio?: string; // bio 是可选的
}
const user1: UserProfile = { id: 1, username: 'Alice' }; // OK
const user2: UserProfile = { id: 2, username: 'Bob', bio: 'Developer' }; // OK
2. 只读属性(Readonly Properties)
我们可以使用 readonly
关键字来防止对象属性在创建后被修改,这对于创建不可变数据非常有用。
typescript
interface Point {
readonly x: number;
readonly y: number;
}
const p1: Point = { x: 10, y: 20 };
p1.x = 5; // Error: 无法为"x"赋值,因为它是只读属性。
3. 函数类型
接口也能用来定义函数的签名(参数类型和返回值类型)。
typescript
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc = function (src: string, sub: string) {
let result = src.search(sub);
return result > -1;
};
console.log(mySearch('hello', 'll'));
4. 可索引类型(Indexable Types)
接口可以描述那些可以通过索引得到的类型,比如数组和对象。
typescript
interface StringArray {
[index: number]: string; // 索引是数字,值是字符串
}
let myArray: StringArray;
myArray = ['Bob', 'Fred'];
let myStr: string = myArray[0]; // OK
console.log(myStr);
interface Dictionary {
[key: string]: any; // 索引是字符串,值是任意类型
}
let user: Dictionary = {
name: '张三',
age: 18,
sex: '男',
}
console.log(user.name);
5. 类实现(Class Implementations)
接口可以被类(Class)implements
(实现),强制一个类必须遵循接口定义的契约。
typescript
interface ClockInterface {
currentTime: Date;
setTime(d: Date): void;
}
class Clock implements ClockInterface {
currentTime: Date = new Date();
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) {
this.currentTime.setHours(h);
this.currentTime.setMinutes(m);
}
printTime() {
console.log(this.currentTime.toLocaleTimeString());
}
}
let clock = new Clock(12, 30);
clock.printTime(); //12:30:43
clock.setTime(new Date('2024-5-6 09:30:43'));
clock.printTime(); //09:30:43
三、接口的扩展与合并
1. 继承(Extends)
一个接口可以像类一样继承另一个接口,从而复用和扩展类型定义。
typescript
interface Shape {
color: string;
}
interface PenStroke {
penWidth: number;
}
// Square 继承了 Shape 和 PenStroke
interface Square extends Shape, PenStroke {
sideLength: number;
}
let square: Square = {
color: 'blue',
penWidth: 5.0,
sideLength: 10,
};
2. 声明合并(Declaration Merging)
这是一个接口独有的、非常强大的特性。如果你在同一个作用域内定义了两个同名的接口,它们会自动合并成一个单一的接口。
typescript
interface Box {
height: number;
width: number;
}
interface Box {
scale: number;
}
// 合并后,Box 接口同时拥有 height, width, 和 scale 属性
const box: Box = { height: 5, width: 6, scale: 10 };
常用的用法 扩展第三方库的类型定义。例如,如果你想为 window
对象添加一个自定义属性,你可以这样做,而不会覆盖原有的定义:
typescript
// 在你的 .d.ts 文件中
declare global {
interface Window {
myAppConfig: object;
}
}
// 现在你可以在代码中安全地访问它
window.myAppConfig = { version: '1.0' };
总结
如果你喜欢本教程,记得点赞+收藏!关注我获取更多TypeScript开发干货