TypeScript 接口(Interface)完全笔记
一、接口概述 🎯
接口的作用:约束 对象、函数、类 的类型结构
接口就像一份契约,规定了数据应该有的形状和行为
二、对象类型接口 📦
基础用法
// 定义对象接口
interface Person {
name: string;
age: number;
}
// 使用接口约束对象
let alice: Person = {
name: "Alice",
age: 25
};
⚠️ 重点:多余属性检查
当直接给函数传参对象自变量时,TypeScript 会进行多余属性检查:
interface Person {
name: string;
age: number;
}
function greet(person: Person) {
console.log(`Hello, ${person.name}`);
}
// ❌ 错误:对象自变量中有多余的属性 'id'
greet({
name: "Alice",
age: 25,
id: 1 // 多余属性
});
// ✅ 解决方案一:类型断言
greet({
name: "Alice",
age: 25,
id: 1
} as Person);
// ✅ 解决方案二:索引签名
interface Person {
name: string;
age: number;
[prop: string]: any; // 允许任意额外属性
}
// ✅ 解决方案三:定义变量(绕过多余属性检查)
let alice = {
name: "Alice",
age: 25,
id: 1
};
greet(alice); // ✅ 变量传参不会触发出多余属性检查
对象接口的高级特性
interface User {
readonly id: number; // 只读属性
name: string;
age?: number; // 可选属性
[key: string]: unknown; // 索引签名(允许额外属性)
}
三、函数类型接口 🎭
函数定义的四种方式
方式一:直接定义(最基础)
function add(x: number, y: number): number {
return x + y;
}
方式二:变量定义函数类型
// 定义函数类型的变量
let add: (x: number, y: number) => number;
// 实现
add = (x, y) => {
return x + y;
};
// 或者直接赋值
let multiply: (x: number, y: number) => number = (x, y) => x * y;
方式三:类型别名定义
// 定义类型别名
type Add = (x: number, y: number) => number;
// 使用类型别名
let add: Add = (x, y) => {
return x + y;
};
// 更简洁的写法
let subtract: Add = (x, y) => x - y;
方式四:接口定义函数类型 ⭐
// 使用接口定义函数类型
interface Add {
(x: number, y: number): number;
}
// 使用
let add: Add = (x, y) => {
return x + y;
};
// 也可以定义更复杂的函数接口
interface MathOperation {
(x: number, y: number): number;
description?: string; // 函数可以有属性
}
const multiply: MathOperation = (x, y) => x * y;
multiply.description = "乘法运算";
四、四种函数定义方式对比 📊
| 方式 | 语法 | 适用场景 | 优点 |
|---|---|---|---|
| 直接定义 | function add(x: number): number {} |
简单函数 | 直观、简单 |
| 变量定义 | let add: (x: number) => number |
函数表达式 | 灵活 |
| 类型别名 | type Add = (x: number) => number |
复用函数类型 | 可复用、可读性好 |
| 接口定义 | interface Add { (x: number): number } |
复杂函数类型 | 可扩展、可合并 |
完整示例:所有方式对比
// 1. 直接定义
function fn1(x: number, y: number): number {
return x + y;
}
// 2. 变量定义
let fn2: (x: number, y: number) => number = (x, y) => x + y;
// 3. 类型别名
type Fn3 = (x: number, y: number) => number;
let fn3: Fn3 = (x, y) => x + y;
// 4. 接口定义
interface Fn4 {
(x: number, y: number): number;
}
let fn4: Fn4 = (x, y) => x + y;
五、接口的其他应用 🚀
1. 类类型接口
interface ClockInterface {
currentTime: Date;
setTime(d: Date): void;
}
class Clock implements ClockInterface {
currentTime: Date = new Date();
setTime(d: Date): void {
this.currentTime = d;
}
}
2. 接口继承
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
let myDog: Dog = {
name: "Rex",
breed: "German Shepherd"
};
3. 混合类型接口
interface Counter {
(start: number): string; // 函数调用
interval: number; // 属性
reset(): void; // 方法
}
function getCounter(): Counter {
let counter = function(start: number) {
return `Count: ${start}`;
} as Counter;
counter.interval = 1000;
counter.reset = () => {};
return counter;
}
📌 核心要点总结
1. 接口的三种主要用途
- ✅ 约束对象的类型
- ✅ 约束函数的类型
- ✅ 约束类的结构
2. 对象接口注意事项
- 多余属性检查:直接传对象自变量时会触发
- 绕过方法:类型断言、索引签名、先赋值给变量
- 属性修饰符:
readonly(只读)、?(可选)
3. 函数接口四种定义方式
- 直接定义:最基础的方式
- 变量定义:适合函数表达式
- 类型别名:适合复用函数类型
- 接口定义:适合复杂或需要扩展的函数类型
4. 选择建议
- 简单函数:直接定义
- 需要复用:类型别名
- 复杂结构:接口定义
- 回调类型:变量定义或类型别名
💡 小贴士:定义函数类型时,优先使用类型别名(
type)因为它更简洁;需要扩展或合并时使用接口(interface)
浙公网安备 33010602011771号