TypeScript接口

108 阅读3分钟

一、前言

在 TypeScript 中,接口(Interface) 是一种非常重要的工具,它允许我们为对象的形状(shape)设定结构规范,从而提高代码的可维护性、可读性和健壮性。

本文将带你从零开始学习 TypeScript 接口,包括:

✅ 接口的基本语法
✅ 属性修饰符(可选、只读)
✅ 方法定义与函数类型接口
✅ 接口继承与实现
✅ 数组类型与索引签名
✅ 类对接口的实现
✅ 接口 vs 类型别名(interface vs type)
✅ 实际开发中的应用案例

并通过完整的代码示例帮助你快速上手并掌握接口的强大功能。

二、什么是接口?

✅ 定义:

接口是一种定义对象结构的方式,它不包含具体的实现逻辑,只描述一个对象应该具备哪些属性和方法。

⚠️ 接口是 TypeScript 提供的一种静态类型检查机制,不会影响最终的 JavaScript 输出。

三、接口的基本用法

✅ 示例:定义一个简单的接口

interface Person {
  name: string;
  age: number;
  sayHello(): void;
}

const user: Person = {
  name: "Alice",
  age: 25,
  sayHello() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

user.sayHello(); // 输出:Hello, my name is Alice

四、接口中的属性修饰符

✅ 1. 可选属性(Optional Properties)

通过 ? 标记某个属性为可选。

interface User {
  id: number;
  name: string;
  email?: string; // 可选属性
}

✅ 2. 只读属性(Readonly Properties)

使用 readonly 关键字限制属性只能在初始化时赋值。

interface Product {
  readonly id: number;
  name: string;
}

const product: Product = { id: 1, name: "Laptop" };
// product.id = 2; ❌ 报错:id 是只读属性

五、函数类型接口

接口不仅可以描述对象,还可以用于定义函数的参数和返回值类型。

✅ 示例:定义函数接口

interface SumFunction {
  (a: number, b: number): number;
}

const add: SumFunction = (x, y) => x + y;

console.log(add(3, 5)); // 输出:8

六、数组类型接口与索引签名

✅ 1. 数组类型接口

interface StringArray {
  [index: number]: string;
}

const fruits: StringArray = ["Apple", "Banana"];
console.log(fruits[0]); // Apple

✅ 2. 索引签名(Index Signature)

接口中也可以定义字符串索引签名,适用于动态键的对象。

interface Dictionary {
  [key: string]: number;
}

const scores: Dictionary = {
  math: 90,
  english: 85
};

七、接口继承(Extends)

一个接口可以通过 extends 继承另一个或多个接口。

✅ 单继承示例:

interface Animal {
  name: string;
}

interface Dog extends Animal {
  breed: string;
}

const dog: Dog = {
  name: "Buddy",
  breed: "Golden Retriever"
};

✅ 多继承示例:

interface Identifiable {
  id: number;
}

interface Timestamped {
  createdAt: Date;
}

interface LogEntry extends Identifiable, Timestamped {
  message: string;
}

const entry: LogEntry = {
  id: 1,
  createdAt: new Date(),
  message: "System started"
};

八、类实现接口(Implements)

类可以使用 implements 来实现一个或多个接口,并必须提供接口中定义的所有属性和方法。

✅ 示例:类实现接口

interface Logger {
  log(message: string): void;
}

class ConsoleLogger implements Logger {
  log(message: string): void {
    console.log(`[LOG] ${message}`);
  }
}

const logger = new ConsoleLogger();
logger.log("Application started"); // 输出:[LOG] Application started

九、接口 vs 类型别名(Interface vs Type)

特性InterfaceType
是否支持合并声明✅ 是(自动合并)❌ 否
是否支持继承✅ 是(extends)✅ 是(交叉类型)
是否支持类实现✅ 是✅ 是
是否适合大型项目✅ 更推荐✅ 也适用
是否可以是联合类型❌ 否✅ 是

✅ 示例对比:

type Point = {
  x: number;
  y: number;
};

interface Point {
  x: number;
  y: number;
}

两者在大多数情况下等价,但在大型项目中建议优先使用 interface,因为它支持声明合并和更清晰的面向对象语义。

十、实际开发中的应用场景

✅ 场景1:定义 API 响应格式

interface ApiResponse<T> {
  status: "success" | "error";
  data?: T;
  error?: string;
}

function fetchUser(): ApiResponse<{ id: number; name: string }> {
  return {
    status: "success",
    data: { id: 1, name: "Alice" }
  };
}

✅ 场景2:组件 props 类型定义(React)

interface ButtonProps {
  label: string;
  onClick?: () => void;
  disabled?: boolean;
}

function Button({ label, onClick, disabled }: ButtonProps) {
  return (
    <button onClick={onClick} disabled={disabled}>
      {label}
    </button>
  );
}

十一、注意事项与最佳实践

场景建议
是否推荐使用 readonly✅ 推荐用于防止意外修改数据
是否推荐使用可选属性✅ 推荐用于部分字段非必填的场景
接口命名规范✅ 使用大驼峰命名法(如 UserProfile
接口合并✅ 在模块化项目中合理利用接口合并特性
接口嵌套✅ 避免过度嵌套,保持简洁易读

十二、总结对比表:TypeScript 接口常用特性一览

特性示例说明
基础接口定义interface Person { name: string }描述对象结构
可选属性email?: string属性可有可无
只读属性readonly id: number初始化后不可修改
函数类型接口(a: number): number定义函数参数与返回值
数组接口[index: number]: string描述数组结构
索引签名[key: string]: any支持任意键的对象
接口继承interface Child extends Parent实现接口复用
类实现接口class A implements B强制实现特定行为
接口合并多个同名 interface 自动合并模块化开发利器
接口 vs 类型别名interface / type推荐 interface 用于 OOP

十三、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!