目录
接口概述
什么是接口?
接口(Interface)是 TypeScript 的核心特性之一,用于定义对象的结构和契约。接口描述了对象应该具有的属性和方法,但不提供具体的实现。它是一种强大的方式来定义代码中的契约。
接口的作用
- 类型检查:确保对象符合预期的结构
- 代码契约:定义组件之间的交互规范
- 文档化:接口本身就是很好的文档
- IDE 支持:提供自动完成和类型提示
- 重构安全:类型系统帮助安全地重构代码
接口 vs 类型别名
// 接口定义
interface User {
name: string;
age: number;
}
// 类型别名定义
type UserType = {
name: string;
age: number;
};
// 主要区别:
// 1. 接口可以被继承和实现
// 2. 接口可以声明合并
// 3. 类型别名更灵活,支持联合类型、条件类型等
基础接口定义
1. 简单接口
// 基础接口定义
interface Person {
firstName: string;
lastName: string;
age: number;
}
// 使用接口
function greet(person: Person): string {
return `Hello, ${person.firstName} ${person.lastName}!`;
}
// 创建符合接口的对象
let user: Person = {
firstName: "张",
lastName: "三",
age: 30
};
console.log(greet(user)); // "Hello, 张 三!"
2. 嵌套接口
// 地址接口
interface Address {
street: string;
city: string;
zipCode: string;
country: string;
}
// 联系方式接口
interface Contact {
email: string;
phone?: string;
address: Address;
}
// 用户接口
interface User {
id: number;
name: string;
contact: Contact;
createdAt: Date;
}
// 使用嵌套接口
let user: User = {
id: 1,
name: "张三",
contact: {
email: "zhangsan@example.com",
phone: "13800138000",
address: {
street: "长安街1号",
city: "北京",
zipCode: "100000",
country: "中国"
}
},
createdAt: new Date()
};
3. 接口的额外属性检查
interface Config {
apiUrl: string;
timeout: number;
}
// 直接传递对象字面量会进行严格检查
function initApp(config: Config): void {
console.log(`API URL: ${config.apiUrl}, Timeout: ${config.timeout}`);
}
// ❌ 错误:对象字面量只能指定已知属性
// initApp({
// apiUrl: "https://api.example.com",
// timeout: 5000,
// debug: true // 额外属性会报错
// });
// ✅ 解决方案1:使用类型断言
initApp({
apiUrl: "https://api.example.com",
timeout: 5000,
debug: true
} as Config);
// ✅ 解决方案2:先赋值给变量
let config = {
apiUrl: "https://api.example.com",
timeout: 5000,
debug: true
};
initApp(config);
// ✅ 解决方案3:使用索引签名
interface FlexibleConfig {
apiUrl: string;
timeout: number;
[propName: string]: any;
}
可选属性和只读属性
1. 可选属性
// 可选属性使用 ? 标记
interface User {
id: number;
name: string;
email?: string; // 可选属性
phone?: string; // 可选属性
avatar?: string; // 可选属性
}
// 创建用户时可以省略可选属性
let user1: User = {
id: 1,
name: "张三"
// email, phone, avatar 都可以省略
};
let user2: User = {
id: 2,
name: "李四",
email: "lisi@example.com"
// phone, avatar 可以省略
};
// 函数参数中的可选属性
function createUser(userData: {
name: string;
email?: string;
age?: number;
}): User {
return {
id: Date.now(),
name: userData.name,
email: userData.email,
// 处理可选属性的默认值
...userData
};
}
// 使用
let newUser1 = createUser({ name: "王五" });
let newUser2 = createUser({ name: "赵六", email: "zhaoliu@example.com", age: 25 });
2. 只读属性
// 只读属性使用 readonly 标记
interface ReadonlyUser {
readonly id: number; // 只读属性
readonly createdAt: Date; // 只读属性
name: string; // 可修改属性
email?: string; // 可选且可修改
}
// 创建对象
let user: ReadonlyUser = {
id: 1,
createdAt: new Date(),
name: "张三",
email: "zhangsan@example.com"
};
// 可以修改非只读属性
user.name = "张三丰"; // ✅ 正确
user.email = "zhangsan@qq.com"; // ✅ 正确
// 不能修改只读属性
// user.id = 2; // ❌ 错误:只读属性
// user.createdAt = new Date(); // ❌ 错误:只读属性
// 只读数组
interface ReadonlyArrayExample {
readonly items: readonly string[];
}
let example: ReadonlyArrayExample = {
items: ["a", "b", "c"]
};
// example.items.push("d"); // ❌ 错误:只读数组
// example.items[0] = "x"; // ❌ 错误:只读数组
console.log(example.items[0]); // ✅ 正确:可以读取
3. 组合可选和只读属性
// 组合使用可选和只读属性
interface Product {
readonly id: number; // 只读必需属性
readonly createdAt: Date; // 只读必需属性
name: string; // 必需属性
description?: string; // 可选属性
readonly category?: string; // 只读可选属性
price: number; // 必需属性
readonly originalPrice?: number; // 只读可选属性
}
// 创建产品
let product: Product = {
id: 1,
createdAt: new Date(),
name: "iPhone 15",
description: "最新款 iPhone",
category: "手机",
price: 5999,
originalPrice: 6999
};
// 可以修改的属性
product.name = "iPhone 15 Pro";
product.description = "iPhone 15 Pro 版本";
product.price = 7999;
// 不能修改只读属性
// product.id = 2; // ❌ 错误
// product.createdAt = new Date(); // ❌ 错误
// product.category = "电脑"; // ❌ 错误
// product.originalPrice = 8999; // ❌ 错误
函数类型接口
1. 基础函数接口
// 定义函数类型接口
interface MathOperation {
(a: number, b: number): number;
}
// 实现函数接口
let add: MathOperation = function(a: number, b: number): number {
return a + b;
};
let multiply: MathOperation = (a, b) => a * b; // 参数类型可以省略
// 使用函数
console.log(add(5, 3)); // 8
console.log(multiply(4, 7)); // 28
// 更复杂的函数接口
interface StringProcessor {
(input: string, options?: { uppercase?: boolean; trim?: boolean }): string;
}
let processString: StringProcessor = (input, options = {}) => {
let result = input;
if (options.trim) {
result = result.trim();
}
if (options.uppercase) {
result = result.toUpperCase();
}
return result;
};
console.log(processString(" hello world ", { trim: true, uppercase: true })); // "HELLO WORLD"
2. 带属性的函数接口
// 函数接口可以有属性和方法
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
// 实现带属性的函数接口
function getCounter(): Counter {
let counter = function(start: number) {
return `Started counting from ${start}`;
} as Counter;
counter.interval = 1000;
counter.reset = function() {
console.log("Counter has been reset");
};
return counter;
}
let myCounter = getCounter();
console.log(myCounter(10)); // "Started counting from 10"
console.log(myCounter.interval); // 1000
myCounter.reset(); // "Counter has been reset"
3. 泛型函数接口
// 泛型函数接口
interface GenericFunction<T, U> {
(input: T): U;
}
// 字符串转数字
let stringToNumber: GenericFunction<string, number> = (input) => {
return parseInt(input, 10);
};
// 数组转字符串
let arrayToString: GenericFunction<any[], string> = (input) => {
return input.join(', ');
};
// 更复杂的泛型函数接口
interface Transformer<T, U> {
transform(input: T): U;
reverse?(output: U): T;
}
class StringNumberTransformer implements Transformer<string, number> {
transform(input: string): number {
return parseFloat(input);
}
reverse(output: number): string {
return output.toString();
}
}
let transformer = new StringNumberTransformer();
console.log(transformer.transform("123.45")); // 123.45
console.log(transformer.reverse(123.45)); // "123.45"
4. 函数重载接口
// 函数重载接口
interface Overloaded {
(x: string): string;
(x: number): number;
(x: boolean): boolean;
}
// 实现重载接口
let overloadedFunction: Overloaded = function(x: any): any {
if (typeof x === 'string') {
return x.toUpperCase();
} else if (typeof x === 'number') {
return x * 2;
} else if (typeof x === 'boolean') {
return !x;
}
};
// 使用
console.log(overloadedFunction("hello")); // "HELLO"
console.log(overloadedFunction(42)); // 84
console.log(overloadedFunction(true)); // false
可索引类型接口
1. 字符串索引签名
// 字符串索引接口
interface StringDictionary {
[key: string]: string;
}
let dict: StringDictionary = {
"name": "张三",
"city": "北京",
"country": "中国"
};
// 动态访问属性
console.log(dict["name"]); // "张三"
console.log(dict.city); // "北京"
// 动态添加属性
dict["email"] = "zhangsan@example.com";
dict.phone = "13800138000";
// 更复杂的字符串索引
interface FlexibleObject {
[key: string]: string | number | boolean;
// 必须确保具体属性的类型是索引签名类型的子类型
name: string; // ✅ string 是 string | number | boolean 的子类型
age: number; // ✅ number 是 string | number | boolean 的子类型
isActive: boolean; // ✅ boolean 是 string | number | boolean 的子类型
}
2. 数字索引签名
// 数字索引接口
interface NumberArray {
[index: number]: string;
}
let fruits: NumberArray = ["apple", "banana", "orange"];
console.log(fruits[0]); // "apple"
console.log(fruits[1]); // "banana"
// 数字索引的类型必须是字符串索引类型的子类型
interface MixedArray {
[index: number]: string; // 数字索引返回 string
[key: string]: string | number; // 字符串索引返回 string | number
length: number; // 具体属性必须符合字符串索引类型
}
let mixedArray: MixedArray = ["a", "b", "c"];
mixedArray.length = 3;
mixedArray["customProp"] = "custom";
mixedArray["numericProp"] = 42;
3. 只读索引签名
// 只读索引签名
interface ReadonlyStringArray {
readonly [index: number]: string;
}
let readonlyArray: ReadonlyStringArray = ["a", "b", "c"];
console.log(readonlyArray[0]); // "a" - 可以读取
// readonlyArray[0] = "x"; // ❌ 错误:只读索引签名
// 只读字典
interface ReadonlyDictionary {
readonly [key: string]: any;
}
let readonlyDict: ReadonlyDictionary = {
name: "张三",
age: 30
};
console.log(readonlyDict.name); // "张三" - 可以读取
// readonlyDict.name = "李四"; // ❌ 错误:只读
4. 复杂索引签名示例
// 缓存接口
interface Cache<T> {
[key: string]: T;
get(key: string): T | undefined;
set(key: string, value: T): void;
has(key: string): boolean;
delete(key: string): boolean;
clear(): void;
}
// 实现缓存
class MemoryCache<T> implements Cache<T> {
[key: string]: any; // 允许动态属性
private data: { [key: string]: T } = {};
get(key: string): T | undefined {
return this.data[key];
}
set(key: string, value: T): void {
this.data[key] = value;
}
has(key: string): boolean {
return key in this.data;
}
delete(key: string): boolean {
if (this.has(key)) {
delete this.data[key];
return true;
}
return false;
}
clear(): void {
this.data = {};
}
}
// 使用缓存
let userCache = new MemoryCache<User>();
userCache.set("user1", { id: 1, name: "张三" });
console.log(userCache.get("user1")); // { id: 1, name: "张三" }
类类型接口
1. 基础类接口
// 定义类接口
interface Flyable {
fly(): void;
}
interface Swimmable {
swim(): void;
}
// 类实现接口
class Bird implements Flyable {
fly(): void {
console.log("Bird is flying");
}
}
class Fish implements Swimmable {
swim(): void {
console.log("Fish is swimming");
}
}
// 类实现多个接口
class Duck implements Flyable, Swimmable {
fly(): void {
console.log("Duck is flying");
}
swim(): void {
console.log("Duck is swimming");
}
}
// 使用
let bird = new Bird();
let fish = new Fish();
let duck = new Duck();
bird.fly(); // "Bird is flying"
fish.swim(); // "Fish is swimming"
duck.fly(); // "Duck is flying"
duck.swim(); // "Duck is swimming"
2. 接口描述类的公共部分
// 接口只描述类的公共部分
interface ClockInterface {
currentTime: Date;
setTime(d: Date): void;
}
class Clock implements ClockInterface {
currentTime: Date = new Date();
constructor(h: number, m: number) {
// 构造函数不在接口中
}
setTime(d: Date): void {
this.currentTime = d;
}
// 私有方法不需要在接口中声明
private tick(): void {
console.log("tick");
}
}
3. 构造函数接口
// 构造函数接口
interface ClockConstructor {
new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
tick(): void;
}
// 工厂函数使用构造函数接口
function createClock(
ctor: ClockConstructor,
hour: number,
minute: number
): ClockInterface {
return new ctor(hour, minute);
}
// 实现类
class DigitalClock implements ClockInterface {
constructor(h: number, m: number) {}
tick(): void {
console.log("beep beep");
}
}
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) {}
tick(): void {
console.log("tick tock");
}
}
// 使用工厂函数
let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);
digital.tick(); // "beep beep"
analog.tick(); // "tick tock"
4. 抽象类与接口结合
// 接口定义契约
interface Drawable {
draw(): void;
getArea(): number;
}
interface Colorable {
color: string;
setColor(color: string): void;
}
// 抽象基类
abstract class Shape implements Drawable, Colorable {
color: string = "black";
setColor(color: string): void {
this.color = color;
}
// 抽象方法,子类必须实现
abstract draw(): void;
abstract getArea(): number;
// 具体方法,子类可以继承
describe(): string {
return `A ${this.color} shape with area ${this.getArea()}`;
}
}
// 具体实现类
class Circle extends Shape {
constructor(private radius: number) {
super();
}
draw(): void {
console.log(`Drawing a circle with radius ${this.radius}`);
}
getArea(): number {
return Math.PI * this.radius * this.radius;
}
}
class Rectangle extends Shape {
constructor(private width: number, private height: number) {
super();
}
draw(): void {
console.log(`Drawing a rectangle ${this.width}x${this.height}`);
}
getArea(): number {
return this.width * this.height;
}
}
// 使用
let circle = new Circle(5);
circle.setColor("red");
circle.draw();
console.log(circle.describe());
let rectangle = new Rectangle(10, 8);
rectangle.setColor("blue");
rectangle.draw();
console.log(rectangle.describe());
接口继承
1. 单接口继承
// 基础接口
interface Animal {
name: string;
age: number;
}
// 继承接口
interface Dog extends Animal {
breed: string;
bark(): void;
}
// 使用继承的接口
let myDog: Dog = {
name: "Buddy",
age: 3,
breed: "Golden Retriever",
bark() {
console.log("Woof! Woof!");
}
};
myDog.bark(); // "Woof! Woof!"
2. 多接口继承
// 多个基础接口
interface Flyable {
maxAltitude: number;
fly(): void;
}
interface Swimmable {
maxDepth: number;
swim(): void;
}
interface Walkable {
maxSpeed: number;
walk(): void;
}
// 多重继承
interface SuperAnimal extends Flyable, Swimmable, Walkable {
name: string;
specialAbility(): void;
}
// 实现多重继承的接口
let superPet: SuperAnimal = {
name: "Super Pet",
maxAltitude: 1000,
maxDepth: 50,
maxSpeed: 30,
fly() {
console.log(`${this.name} is flying up to ${this.maxAltitude}m`);
},
swim() {
console.log(`${this.name} is swimming down to ${this.maxDepth}m`);
},
walk() {
console.log(`${this.name} is walking at ${this.maxSpeed}km/h`);
},
specialAbility() {
console.log(`${this.name} has super powers!`);
}
};
3. 接口继承类
// 类定义
class Control {
private state: any;
protected setState(state: any): void {
this.state = state;
}
}
// 接口继承类
interface SelectableControl extends Control {
select(): void;
}
// 只有 Control 的子类才能实现 SelectableControl
class Button extends Control implements SelectableControl {
select(): void {
console.log("Button selected");
this.setState({ selected: true });
}
}
class TextBox extends Control implements SelectableControl {
select(): void {
console.log("TextBox selected");
this.setState({ selected: true });
}
}
// 错误示例:非 Control 子类无法实现 SelectableControl
// class Image implements SelectableControl {
// select(): void {} // ❌ 错误:缺少私有成员 state
// }
4. 复杂继承层次
// 基础接口层次
interface Entity {
id: number;
createdAt: Date;
updatedAt?: Date;
}
interface User extends Entity {
username: string;
email: string;
}
interface AdminUser extends User {
permissions: string[];
lastLoginAt?: Date;
}
interface SuperAdmin extends AdminUser {
canDeleteUsers: boolean;
canModifySystem: boolean;
}
// 使用复杂继承
let superAdmin: SuperAdmin = {
// Entity 属性
id: 1,
createdAt: new Date(),
updatedAt: new Date(),
// User 属性
username: "superadmin",
email: "admin@example.com",
// AdminUser 属性
permissions: ["read", "write", "delete", "admin"],
lastLoginAt: new Date(),
// SuperAdmin 属性
canDeleteUsers: true,
canModifySystem: true
};
// 类型兼容性
let user: User = superAdmin; // ✅ 正确:SuperAdmin 包含 User 的所有属性
let admin: AdminUser = superAdmin; // ✅ 正确:SuperAdmin 包含 AdminUser 的所有属性
混合类型接口
1. 函数与对象的混合
// 既是函数又是对象的接口
interface Counter {
(start: number): string;
interval: number;
reset(): void;
increment(): number;
decrement(): number;
}
// 创建混合类型对象
function getCounter(): Counter {
let counter = function(start: number) {
counter.current = start;
return `Counter started at ${start}`;
} as Counter;
counter.current = 0;
counter.interval = 1000;
counter.reset = function() {
this.current = 0;
console.log("Counter reset to 0");
};
counter.increment = function() {
return ++this.current;
};
counter.decrement = function() {
return --this.current;
};
return counter;
}
// 使用混合类型
let myCounter = getCounter();
// 作为函数调用
console.log(myCounter(10)); // "Counter started at 10"
// 作为对象使用
console.log(myCounter.interval); // 1000
console.log(myCounter.increment()); // 11
console.log(myCounter.decrement()); // 10
myCounter.reset(); // "Counter reset to 0"
2. 复杂混合类型
// 事件发射器混合类型
interface EventEmitter {
// 函数签名
(event: string, ...args: any[]): void;
// 对象属性和方法
events: { [event: string]: Function[] };
on(event: string, listener: Function): void;
off(event: string, listener: Function): void;
once(event: string, listener: Function): void;
removeAllListeners(event?: string): void;
}
// 实现混合类型
function createEventEmitter(): EventEmitter {
let emitter = function(event: string, ...args: any[]) {
const listeners = emitter.events[event];
if (listeners) {
listeners.forEach(listener => listener(...args));
}
} as EventEmitter;
emitter.events = {};
emitter.on = function(event: string, listener: Function) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(listener);
};
emitter.off = function(event: string, listener: Function) {
if (this.events[event]) {
const index = this.events[event].indexOf(listener);
if (index > -1) {
this.events[event].splice(index, 1);
}
}
};
emitter.once = function(event: string, listener: Function) {
const onceWrapper = (...args: any[]) => {
listener(...args);
this.off(event, onceWrapper);
};
this.on(event, onceWrapper);
};
emitter.removeAllListeners = function(event?: string) {
if (event) {
delete this.events[event];
} else {
this.events = {};
}
};
return emitter;
}
// 使用复杂混合类型
let emitter = createEventEmitter();
// 添加事件监听器
emitter.on('data', (data: any) => console.log('Data received:', data));
emitter.once('error', (error: Error) => console.error('Error:', error.message));
// 触发事件(作为函数调用)
emitter('data', { id: 1, message: 'Hello' });
emitter('error', new Error('Something went wrong'));
3. 库接口模式
// jQuery 风格的库接口
interface JQueryLike {
// 选择器函数
(selector: string): JQueryLike;
// 链式方法
addClass(className: string): JQueryLike;
removeClass(className: string): JQueryLike;
css(property: string, value: string): JQueryLike;
css(properties: { [key: string]: string }): JQueryLike;
on(event: string, handler: Function): JQueryLike;
// 获取/设置方法
text(): string;
text(content: string): JQueryLike;
html(): string;
html(content: string): JQueryLike;
// 工具方法
each(callback: (index: number, element: any) => void): JQueryLike;
length: number;
}
// 简化实现
function createJQuery(): JQueryLike {
let elements: any[] = [];
let jquery = function(selector: string) {
// 简化的选择器实现
elements = []; // 重置元素数组
return jquery;
} as JQueryLike;
jquery.length = 0;
jquery.addClass = function(className: string) {
// 实现添加类的逻辑
return this;
};
jquery.removeClass = function(className: string) {
// 实现移除类的逻辑
return this;
};
jquery.css = function(property: any, value?: string) {
if (typeof property === 'string' && value) {
// 设置单个 CSS 属性
} else if (typeof property === 'object') {
// 设置多个 CSS 属性
}
return this;
};
jquery.on = function(event: string, handler: Function) {
// 实现事件绑定
return this;
};
jquery.text = function(content?: string) {
if (content === undefined) {
// 获取文本内容
return "";
} else {
// 设置文本内容
return this;
}
} as any;
jquery.html = function(content?: string) {
if (content === undefined) {
// 获取 HTML 内容
return "";
} else {
// 设置 HTML 内容
return this;
}
} as any;
jquery.each = function(callback: (index: number, element: any) => void) {
elements.forEach(callback);
return this;
};
return jquery;
}
// 使用库接口
let $ = createJQuery();
// 链式调用
$('.my-class')
.addClass('active')
.css('color', 'red')
.on('click', () => console.log('Clicked!'))
.text('Hello World');
接口与泛型
1. 泛型接口基础
// 基础泛型接口
interface Container<T> {
value: T;
getValue(): T;
setValue(value: T): void;
}
// 实现泛型接口
class StringContainer implements Container<string> {
constructor(public value: string) {}
getValue(): string {
return this.value;
}
setValue(value: string): void {
this.value = value;
}
}
class NumberContainer implements Container<number> {
constructor(public value: number) {}
getValue(): number {
return this.value;
}
setValue(value: number): void {
this.value = value;
}
}
// 使用
let stringContainer = new StringContainer("Hello");
let numberContainer = new NumberContainer(42);
console.log(stringContainer.getValue()); // "Hello"
console.log(numberContainer.getValue()); // 42
2. 多类型参数的泛型接口
// 多类型参数接口
interface KeyValuePair<K, V> {
key: K;
value: V;
}
interface Dictionary<K, V> {
items: KeyValuePair<K, V>[];
get(key: K): V | undefined;
set(key: K, value: V): void;
has(key: K): boolean;
delete(key: K): boolean;
keys(): K[];
values(): V[];
}
// 实现多类型参数接口
class SimpleDictionary<K, V> implements Dictionary<K, V> {
items: KeyValuePair<K, V>[] = [];
get(key: K): V | undefined {
const item = this.items.find(item => item.key === key);
return item ? item.value : undefined;
}
set(key: K, value: V): void {
const existingItem = this.items.find(item => item.key === key);
if (existingItem) {
existingItem.value = value;
} else {
this.items.push({ key, value });
}
}
has(key: K): boolean {
return this.items.some(item => item.key === key);
}
delete(key: K): boolean {
const index = this.items.findIndex(item => item.key === key);
if (index > -1) {
this.items.splice(index, 1);
return true;
}
return false;
}
keys(): K[] {
return this.items.map(item => item.key);
}
values(): V[] {
return this.items.map(item => item.value);
}
}
// 使用
let stringNumberDict = new SimpleDictionary<string, number>();
stringNumberDict.set("age", 30);
stringNumberDict.set("score", 95);
console.log(stringNumberDict.get("age")); // 30
console.log(stringNumberDict.keys()); // ["age", "score"]
console.log(stringNumberDict.values()); // [30, 95]
3. 泛型约束接口
// 带约束的泛型接口
interface Lengthwise {
length: number;
}
interface Processor<T extends Lengthwise> {
process(item: T): T;
getLength(item: T): number;
}
// 实现约束泛型接口
class StringProcessor implements Processor<string> {
process(item: string): string {
return item.trim().toUpperCase();
}
getLength(item: string): number {
return item.length;
}
}
class ArrayProcessor<T> implements Processor<T[]> {
process(item: T[]): T[] {
return [...item]; // 返回副本
}
getLength(item: T[]): number {
return item.length;
}
}
// 使用
let stringProcessor = new StringProcessor();
console.log(stringProcessor.process(" hello world ")); // "HELLO WORLD"
console.log(stringProcessor.getLength("hello")); // 5
let numberArrayProcessor = new ArrayProcessor<number>();
console.log(numberArrayProcessor.process([1, 2, 3])); // [1, 2, 3]
console.log(numberArrayProcessor.getLength([1, 2, 3, 4])); // 4
4. 条件类型与泛型接口
// 条件类型泛型接口
interface ApiResponse<T> {
success: boolean;
data: T extends string ? { message: T } : T;
timestamp: Date;
}
// 使用条件类型接口
let stringResponse: ApiResponse<string> = {
success: true,
data: { message: "操作成功" }, // T 是 string,所以 data 是 { message: string }
timestamp: new Date()
};
let userResponse: ApiResponse<User> = {
success: true,
data: { id: 1, name: "张三" }, // T 是 User,所以 data 是 User
timestamp: new Date()
};
// 更复杂的条件类型接口
type NonNullable<T> = T extends null | undefined ? never : T;
interface SafeContainer<T> {
value: NonNullable<T>;
hasValue(): boolean;
getValue(): NonNullable<T>;
setValue(value: NonNullable<T>): void;
}
class SafeStringContainer implements SafeContainer<string> {
constructor(public value: string) {}
hasValue(): boolean {
return this.value !== null && this.value !== undefined;
}
getValue(): string {
return this.value;
}
setValue(value: string): void {
this.value = value;
}
}
// 使用
let safeContainer = new SafeStringContainer("Hello");
console.log(safeContainer.hasValue()); // true
console.log(safeContainer.getValue()); // "Hello"
高级接口模式
1. 声明合并
// 接口声明合并
interface User {
name: string;
}
interface User {
age: number;
}
interface User {
email: string;
}
// 合并后的接口等同于:
// interface User {
// name: string;
// age: number;
// email: string;
// }
let user: User = {
name: "张三",
age: 30,
email: "zhangsan@example.com"
};
// 模块扩展示例
declare global {
interface Window {
myCustomProperty: string;
myCustomMethod(): void;
}
}
// 现在可以使用扩展的 Window 接口
window.myCustomProperty = "Hello World";
window.myCustomMethod = () => console.log("Custom method called");
2. 映射类型接口
// 基于现有类型创建新接口
interface Person {
name: string;
age: number;
email: string;
}
// 创建可选版本
type PartialPerson = {
[P in keyof Person]?: Person[P];
};
// 创建只读版本
type ReadonlyPerson = {
readonly [P in keyof Person]: Person[P];
};
// 创建字符串化版本
type StringifiedPerson = {
[P in keyof Person]: string;
};
// 使用映射类型
let partialPerson: PartialPerson = {
name: "张三"
// age 和 email 是可选的
};
let readonlyPerson: ReadonlyPerson = {
name: "李四",
age: 25,
email: "lisi@example.com"
};
// readonlyPerson.name = "王五"; // ❌ 错误:只读属性
let stringifiedPerson: StringifiedPerson = {
name: "赵六",
age: "30", // 必须是字符串
email: "zhaoliu@example.com"
};
3. 模板字面量类型接口
// 模板字面量类型接口
type EventName<T extends string> = `on${Capitalize<T>}`;
interface EventHandlers<T extends Record<string, any>> {
[K in keyof T as EventName<string & K>]: (data: T[K]) => void;
}
// 定义事件类型
interface AppEvents {
userLogin: { userId: number; username: string };
userLogout: { userId: number };
dataUpdate: { table: string; id: number };
}
// 生成事件处理器接口
type AppEventHandlers = EventHandlers<AppEvents>;
// 结果:
// {
// onUserLogin: (data: { userId: number; username: string }) => void;
// onUserLogout: (data: { userId: number }) => void;
// onDataUpdate: (data: { table: string; id: number }) => void;
// }
// 实现事件处理器
class EventManager implements AppEventHandlers {
onUserLogin(data: { userId: number; username: string }): void {
console.log(`User ${data.username} logged in`);
}
onUserLogout(data: { userId: number }): void {
console.log(`User ${data.userId} logged out`);
}
onDataUpdate(data: { table: string; id: number }): void {
console.log(`Data updated in ${data.table}, ID: ${data.id}`);
}
}
4. 递归接口类型
// 递归接口定义
interface TreeNode<T> {
value: T;
children?: TreeNode<T>[];
parent?: TreeNode<T>;
}
interface Tree<T> {
root: TreeNode<T>;
find(value: T): TreeNode<T> | null;
insert(value: T, parent?: TreeNode<T>): TreeNode<T>;
remove(value: T): boolean;
traverse(callback: (node: TreeNode<T>) => void): void;
}
// 实现递归接口
class BinaryTree<T> implements Tree<T> {
root: TreeNode<T>;
constructor(rootValue: T) {
this.root = { value: rootValue };
}
find(value: T): TreeNode<T> | null {
return this.findNode(this.root, value);
}
private findNode(node: TreeNode<T>, value: T): TreeNode<T> | null {
if (node.value === value) {
return node;
}
if (node.children) {
for (const child of node.children) {
const found = this.findNode(child, value);
if (found) return found;
}
}
return null;
}
insert(value: T, parent?: TreeNode<T>): TreeNode<T> {
const newNode: TreeNode<T> = { value, parent };
if (parent) {
if (!parent.children) {
parent.children = [];
}
parent.children.push(newNode);
}
return newNode;
}
remove(value: T): boolean {
const node = this.find(value);
if (!node || !node.parent) return false;
const parent = node.parent;
if (parent.children) {
const index = parent.children.indexOf(node);
if (index > -1) {
parent.children.splice(index, 1);
return true;
}
}
return false;
}
traverse(callback: (node: TreeNode<T>) => void): void {
this.traverseNode(this.root, callback);
}
private traverseNode(node: TreeNode<T>, callback: (node: TreeNode<T>) => void): void {
callback(node);
if (node.children) {
node.children.forEach(child => this.traverseNode(child, callback));
}
}
}
// 使用递归接口
let tree = new BinaryTree<string>("root");
let child1 = tree.insert("child1", tree.root);
let child2 = tree.insert("child2", tree.root);
tree.insert("grandchild1", child1);
tree.traverse(node => console.log(node.value));
// 输出: root, child1, grandchild1, child2
实战应用
1. RESTful API 接口设计
// HTTP 方法类型
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
// 基础 API 响应接口
interface ApiResponse<T = any> {
success: boolean;
data: T;
message: string;
timestamp: Date;
errors?: string[];
}
// 分页响应接口
interface PaginatedResponse<T> extends ApiResponse<T[]> {
pagination: {
page: number;
limit: number;
total: number;
totalPages: number;
};
}
// 用户相关接口
interface User {
id: number;
username: string;
email: string;
firstName: string;
lastName: string;
avatar?: string;
createdAt: Date;
updatedAt: Date;
}
interface CreateUserRequest {
username: string;
email: string;
password: string;
firstName: string;
lastName: string;
}
interface UpdateUserRequest {
email?: string;
firstName?: string;
lastName?: string;
avatar?: string;
}
// API 端点接口
interface ApiEndpoints {
// 用户相关
'GET /users': {
query?: { page?: number; limit?: number; search?: string };
response: PaginatedResponse<User>;
};
'GET /users/:id': {
params: { id: number };
response: ApiResponse<User>;
};
'POST /users': {
body: CreateUserRequest;
response: ApiResponse<User>;
};
'PUT /users/:id': {
params: { id: number };
body: UpdateUserRequest;
response: ApiResponse<User>;
};
'DELETE /users/:id': {
params: { id: number };
response: ApiResponse<null>;
};
}
// API 客户端接口
interface ApiClient {
request<T extends keyof ApiEndpoints>(
endpoint: T,
options?: ApiEndpoints[T] extends { params: infer P }
? ApiEndpoints[T] extends { body: infer B }
? ApiEndpoints[T] extends { query: infer Q }
? { params: P; body: B; query: Q }
: { params: P; body: B }
: ApiEndpoints[T] extends { query: infer Q }
? { params: P; query: Q }
: { params: P }
: ApiEndpoints[T] extends { body: infer B }
? ApiEndpoints[T] extends { query: infer Q }
? { body: B; query: Q }
: { body: B }
: ApiEndpoints[T] extends { query: infer Q }
? { query: Q }
: {}
): Promise<ApiEndpoints[T]['response']>;
}
// 实现 API 客户端
class RestApiClient implements ApiClient {
constructor(private baseUrl: string, private token?: string) {}
async request<T extends keyof ApiEndpoints>(
endpoint: T,
options: any = {}
): Promise<ApiEndpoints[T]['response']> {
const [method, path] = (endpoint as string).split(' ');
let url = this.baseUrl + path;
// 处理路径参数
if (options.params) {
Object.entries(options.params).forEach(([key, value]) => {
url = url.replace(`:${key}`, String(value));
});
}
// 处理查询参数
if (options.query) {
const queryString = new URLSearchParams(options.query).toString();
url += `?${queryString}`;
}
// 准备请求配置
const config: RequestInit = {
method,
headers: {
'Content-Type': 'application/json',
...(this.token && { 'Authorization': `Bearer ${this.token}` })
}
};
// 添加请求体
if (options.body) {
config.body = JSON.stringify(options.body);
}
// 发送请求
const response = await fetch(url, config);
return response.json();
}
}
// 使用示例
async function userApiExample() {
const apiClient = new RestApiClient('https://api.example.com', 'your-token');
// 获取用户列表
const usersResponse = await apiClient.request('GET /users', {
query: { page: 1, limit: 10, search: '张' }
});
// 获取单个用户
const userResponse = await apiClient.request('GET /users/:id', {
params: { id: 1 }
});
// 创建用户
const newUserResponse = await apiClient.request('POST /users', {
body: {
username: 'newuser',
email: 'newuser@example.com',
password: 'password123',
firstName: '新',
lastName: '用户'
}
});
// 更新用户
const updatedUserResponse = await apiClient.request('PUT /users/:id', {
params: { id: 1 },
body: {
firstName: '更新的名字'
}
});
// 删除用户
const deleteResponse = await apiClient.request('DELETE /users/:id', {
params: { id: 1 }
});
}
2. 状态管理接口设计
// 状态管理相关接口
interface State {
user: {
currentUser: User | null;
isAuthenticated: boolean;
loading: boolean;
};
posts: {
items: Post[];
loading: boolean;
error: string | null;
};
ui: {
theme: 'light' | 'dark';
sidebarOpen: boolean;
notifications: Notification[];
};
}
interface Post {
id: number;
title: string;
content: string;
authorId: number;
createdAt: Date;
updatedAt: Date;
}
interface Notification {
id: string;
type: 'info' | 'success' | 'warning' | 'error';
message: string;
timestamp: Date;
read: boolean;
}
// Action 接口
interface Action<T = any> {
type: string;
payload?: T;
}
// 具体 Action 接口
interface UserActions {
LOGIN_START: Action;
LOGIN_SUCCESS: Action<User>;
LOGIN_FAILURE: Action<string>;
LOGOUT: Action;
UPDATE_PROFILE: Action<Partial<User>>;
}
interface PostActions {
FETCH_POSTS_START: Action;
FETCH_POSTS_SUCCESS: Action<Post[]>;
FETCH_POSTS_FAILURE: Action<string>;
CREATE_POST: Action<Omit<Post, 'id' | 'createdAt' | 'updatedAt'>>;
UPDATE_POST: Action<{ id: number; updates: Partial<Post> }>;
DELETE_POST: Action<number>;
}
interface UIActions {
SET_THEME: Action<'light' | 'dark'>;
TOGGLE_SIDEBAR: Action;
ADD_NOTIFICATION: Action<Omit<Notification, 'id' | 'timestamp'>>;
REMOVE_NOTIFICATION: Action<string>;
MARK_NOTIFICATION_READ: Action<string>;
}
// Reducer 接口
interface Reducer<S, A extends Action> {
(state: S, action: A): S;
}
// Store 接口
interface Store<S> {
getState(): S;
dispatch(action: Action): void;
subscribe(listener: (state: S) => void): () => void;
}
// 中间件接口
interface Middleware<S> {
(store: Store<S>): (next: (action: Action) => void) => (action: Action) => void;
}
// 实现状态管理
class StateManager<S> implements Store<S> {
private state: S;
private listeners: Array<(state: S) => void> = [];
private middlewares: Array<Middleware<S>> = [];
constructor(
private reducer: Reducer<S, Action>,
initialState: S,
middlewares: Array<Middleware<S>> = []
) {
this.state = initialState;
this.middlewares = middlewares;
}
getState(): S {
return this.state;
}
dispatch(action: Action): void {
// 应用中间件
let dispatch = (action: Action) => {
this.state = this.reducer(this.state, action);
this.notifyListeners();
};
// 从右到左应用中间件
for (let i = this.middlewares.length - 1; i >= 0; i--) {
dispatch = this.middlewares[i](this)(dispatch);
}
dispatch(action);
}
subscribe(listener: (state: S) => void): () => void {
this.listeners.push(listener);
return () => {
const index = this.listeners.indexOf(listener);
if (index > -1) {
this.listeners.splice(index, 1);
}
};
}
private notifyListeners(): void {
this.listeners.forEach(listener => listener(this.state));
}
}
// 使用示例
const initialState: State = {
user: {
currentUser: null,
isAuthenticated: false,
loading: false
},
posts: {
items: [],
loading: false,
error: null
},
ui: {
theme: 'light',
sidebarOpen: false,
notifications: []
}
};
// 日志中间件
const loggerMiddleware: Middleware<State> = (store) => (next) => (action) => {
console.log('Dispatching:', action);
console.log('Previous state:', store.getState());
next(action);
console.log('Next state:', store.getState());
};
// 创建 store
const rootReducer: Reducer<State, Action> = (state, action) => {
// 简化的 reducer 实现
switch (action.type) {
case 'LOGIN_SUCCESS':
return {
...state,
user: {
...state.user,
currentUser: action.payload,
isAuthenticated: true,
loading: false
}
};
default:
return state;
}
};
const store = new StateManager(rootReducer, initialState, [loggerMiddleware]);
// 使用 store
store.subscribe((state) => {
console.log('State updated:', state);
});
store.dispatch({
type: 'LOGIN_SUCCESS',
payload: {
id: 1,
username: 'testuser',
email: 'test@example.com',
firstName: '测试',
lastName: '用户',
createdAt: new Date(),
updatedAt: new Date()
}
});
3. 插件系统接口设计
// 插件系统接口
interface Plugin {
name: string;
version: string;
description?: string;
dependencies?: string[];
install(context: PluginContext): void | Promise<void>;
uninstall?(context: PluginContext): void | Promise<void>;
activate?(context: PluginContext): void | Promise<void>;
deactivate?(context: PluginContext): void | Promise<void>;
}
interface PluginContext {
app: Application;
config: PluginConfig;
logger: Logger;
events: EventEmitter;
}
interface PluginConfig {
[key: string]: any;
}
interface Logger {
info(message: string, ...args: any[]): void;
warn(message: string, ...args: any[]): void;
error(message: string, ...args: any[]): void;
debug(message: string, ...args: any[]): void;
}
interface EventEmitter {
on(event: string, listener: Function): void;
off(event: string, listener: Function): void;
emit(event: string, ...args: any[]): void;
}
interface Application {
version: string;
config: any;
registerCommand(name: string, handler: Function): void;
registerRoute(path: string, handler: Function): void;
registerMiddleware(middleware: Function): void;
}
// 插件管理器接口
interface PluginManager {
register(plugin: Plugin): void;
unregister(pluginName: string): void;
install(pluginName: string, config?: PluginConfig): Promise<void>;
uninstall(pluginName: string): Promise<void>;
activate(pluginName: string): Promise<void>;
deactivate(pluginName: string): Promise<void>;
getPlugin(name: string): Plugin | undefined;
getInstalledPlugins(): Plugin[];
getActivePlugins(): Plugin[];
}
// 实现插件管理器
class SimplePluginManager implements PluginManager {
private plugins = new Map<string, Plugin>();
private installedPlugins = new Set<string>();
private activePlugins = new Set<string>();
constructor(
private app: Application,
private logger: Logger,
private events: EventEmitter
) {}
register(plugin: Plugin): void {
if (this.plugins.has(plugin.name)) {
throw new Error(`Plugin ${plugin.name} is already registered`);
}
this.plugins.set(plugin.name, plugin);
this.logger.info(`Plugin ${plugin.name} registered`);
}
unregister(pluginName: string): void {
if (this.installedPlugins.has(pluginName)) {
throw new Error(`Cannot unregister installed plugin ${pluginName}`);
}
this.plugins.delete(pluginName);
this.logger.info(`Plugin ${pluginName} unregistered`);
}
async install(pluginName: string, config: PluginConfig = {}): Promise<void> {
const plugin = this.plugins.get(pluginName);
if (!plugin) {
throw new Error(`Plugin ${pluginName} not found`);
}
if (this.installedPlugins.has(pluginName)) {
throw new Error(`Plugin ${pluginName} is already installed`);
}
// 检查依赖
if (plugin.dependencies) {
for (const dep of plugin.dependencies) {
if (!this.installedPlugins.has(dep)) {
throw new Error(`Dependency ${dep} is not installed`);
}
}
}
const context: PluginContext = {
app: this.app,
config,
logger: this.logger,
events: this.events
};
await plugin.install(context);
this.installedPlugins.add(pluginName);
this.logger.info(`Plugin ${pluginName} installed`);
this.events.emit('plugin:installed', { name: pluginName, plugin });
}
async uninstall(pluginName: string): Promise<void> {
const plugin = this.plugins.get(pluginName);
if (!plugin) {
throw new Error(`Plugin ${pluginName} not found`);
}
if (!this.installedPlugins.has(pluginName)) {
throw new Error(`Plugin ${pluginName} is not installed`);
}
if (this.activePlugins.has(pluginName)) {
await this.deactivate(pluginName);
}
const context: PluginContext = {
app: this.app,
config: {},
logger: this.logger,
events: this.events
};
if (plugin.uninstall) {
await plugin.uninstall(context);
}
this.installedPlugins.delete(pluginName);
this.logger.info(`Plugin ${pluginName} uninstalled`);
this.events.emit('plugin:uninstalled', { name: pluginName, plugin });
}
async activate(pluginName: string): Promise<void> {
const plugin = this.plugins.get(pluginName);
if (!plugin) {
throw new Error(`Plugin ${pluginName} not found`);
}
if (!this.installedPlugins.has(pluginName)) {
throw new Error(`Plugin ${pluginName} is not installed`);
}
if (this.activePlugins.has(pluginName)) {
throw new Error(`Plugin ${pluginName} is already active`);
}
const context: PluginContext = {
app: this.app,
config: {},
logger: this.logger,
events: this.events
};
if (plugin.activate) {
await plugin.activate(context);
}
this.activePlugins.add(pluginName);
this.logger.info(`Plugin ${pluginName} activated`);
this.events.emit('plugin:activated', { name: pluginName, plugin });
}
async deactivate(pluginName: string): Promise<void> {
const plugin = this.plugins.get(pluginName);
if (!plugin) {
throw new Error(`Plugin ${pluginName} not found`);
}
if (!this.activePlugins.has(pluginName)) {
throw new Error(`Plugin ${pluginName} is not active`);
}
const context: PluginContext = {
app: this.app,
config: {},
logger: this.logger,
events: this.events
};
if (plugin.deactivate) {
await plugin.deactivate(context);
}
this.activePlugins.delete(pluginName);
this.logger.info(`Plugin ${pluginName} deactivated`);
this.events.emit('plugin:deactivated', { name: pluginName, plugin });
}
getPlugin(name: string): Plugin | undefined {
return this.plugins.get(name);
}
getInstalledPlugins(): Plugin[] {
return Array.from(this.installedPlugins)
.map(name => this.plugins.get(name))
.filter((plugin): plugin is Plugin => plugin !== undefined);
}
getActivePlugins(): Plugin[] {
return Array.from(this.activePlugins)
.map(name => this.plugins.get(name))
.filter((plugin): plugin is Plugin => plugin !== undefined);
}
}
// 示例插件
class AuthPlugin implements Plugin {
name = 'auth';
version = '1.0.0';
description = 'Authentication plugin';
install(context: PluginContext): void {
context.logger.info('Installing auth plugin');
// 注册认证相关的路由
context.app.registerRoute('/login', this.handleLogin);
context.app.registerRoute('/logout', this.handleLogout);
// 注册认证中间件
context.app.registerMiddleware(this.authMiddleware);
// 监听用户事件
context.events.on('user:login', this.onUserLogin);
context.events.on('user:logout', this.onUserLogout);
}
uninstall(context: PluginContext): void {
context.logger.info('Uninstalling auth plugin');
// 清理资源
}
private handleLogin = (req: any, res: any) => {
// 处理登录逻辑
};
private handleLogout = (req: any, res: any) => {
// 处理登出逻辑
};
private authMiddleware = (req: any, res: any, next: Function) => {
// 认证中间件逻辑
next();
};
private onUserLogin = (user: User) => {
console.log(`User ${user.username} logged in`);
};
private onUserLogout = (user: User) => {
console.log(`User ${user.username} logged out`);
};
}
总结
TypeScript 接口是构建类型安全应用程序的基石。通过本指南的学习,您应该掌握了:
核心概念
- 基础接口定义:描述对象结构和契约
- 可选和只读属性:灵活的属性定义
- 函数类型接口:定义函数签名和行为
- 可索引类型接口:处理动态属性访问
高级特性
- 接口继承:构建类型层次结构
- 混合类型接口:组合函数和对象特性
- 泛型接口:创建可重用的类型定义
- 高级模式:声明合并、映射类型、递归类型
实战应用
- API 接口设计:类型安全的网络通信
- 状态管理:结构化的应用状态
- 插件系统:可扩展的架构设计
最佳实践
- 渐进式设计:从简单接口开始,逐步增加复杂性
- 命名规范:使用清晰、一致的命名约定
- 文档化:接口本身就是很好的文档
- 类型安全:充分利用 TypeScript 的类型检查能力
掌握接口设计将帮助您构建更加健壮、可维护和可扩展的 TypeScript 应用程序。在实际项目中,建议从核心业务对象的接口定义开始,逐步扩展到整个应用的类型系统。