Skip to content
第 5 章 前端 ⏱ 10 分钟阅读

第 5 章:接口 ​

学习目标 ​

  • 用 interface 定义对象结构
  • 学会可选属性、只读属性、索引签名
  • 理解接口继承与合并
  • 区分 interface 与 type

一、最基本的接口 ​

typescript
interface User {
  id: number;
  name: string;
  email: string;
}

const tom: User = {
  id: 1,
  name: 'Tom',
  email: 'tom@example.com',
};

// ❌ 少字段会报错
const bad: User = { id: 1, name: 'Tom' };
// Property 'email' is missing in type

二、可选属性与只读属性 ​

typescript
interface Config {
  host: string;
  port?: number;       // 可选
  readonly apiKey: string;  // 只读
}

const cfg: Config = { host: 'localhost', apiKey: 'abc' };
cfg.port = 8080;     // ✅ 可选字段可以赋值
cfg.apiKey = 'xyz';  // ❌ Cannot assign to 'apiKey' because it is read-only

⚠️ 坑 1:只读属性是编译期保护,运行后通过 Object.assign 之类的反射仍可改,真要锁死得用 Object.freeze()。

三、函数类型接口 ​

typescript
interface GreetFn {
  (name: string): string;
}

const greet: GreetFn = (name) => `Hello, ${name}`;
greet('Tom');  // 'Hello, Tom'

四、可索引接口(索引签名) ​

typescript
// 字符串索引
interface Dict {
  [key: string]: string;
}

const dict: Dict = {
  name: 'Tom',
  email: 'tom@example.com',
};

// 数字索引(类似数组)
interface StringArray {
  [index: number]: string;
}

const arr: StringArray = ['a', 'b', 'c'];
arr[0];  // 'a'

⚠️ 坑 2:索引签名要求所有显式属性必须兼容其类型,下面这种会报错:

typescript
interface Bad {
  [key: string]: string;
  age: number;  // ❌ number 不兼容 string
}

五、接口继承(extends) ​

typescript
interface Animal {
  name: string;
}

interface Dog extends Animal {
  breed: string;
}

const d: Dog = {
  name: '旺财',
  breed: '柴犬',
};

// 多继承
interface Pet {
  owner: string;
}

interface Cat extends Animal, Pet {
  color: string;
}

const c: Cat = { name: '小花', owner: 'Tom', color: '白' };

六、接口合并(Declaration Merging) ​

同名 interface 会自动合并:

typescript
interface Box {
  width: number;
}

interface Box {
  height: number;
}

// 等价于:
interface Box {
  width: number;
  height: number;
}

const b: Box = { width: 10, height: 20 };

⚠️ 坑 3:type 不能合并,会报重复定义;interface 可以。这在扩展第三方库类型时特别有用。

七、接口继承类 ​

typescript
class Control {
  state: number = 0;
}

interface SelectableControl extends Control {
  select(): void;
}

class Button extends Control implements SelectableControl {
  select(): void {
    console.log('selected');
  }
}

八、interface vs type 速查 ​

场景选什么原因
对象/函数结构interface可继承、可合并,语义清晰
联合/交叉/元组typeinterface 表达不了
工具类型组合type灵活
需要 declare mergeinterfacetype 做不到

九、实战:组件 Props ​

typescript
interface ButtonProps {
  label: string;
  disabled?: boolean;
  onClick: (e: MouseEvent) => void;
  variant?: 'primary' | 'secondary' | 'danger';
}

function Button(props: ButtonProps): void {
  console.log(props.label);
}

Button({ label: '提交', onClick: (e) => console.log(e) });

十、本章小结 ​

要点关键
基本接口interface Name { ... } 定义对象结构
可选 / 只读prop? 可选,readonly prop 只读
索引签名[key: string]: T 描述动态 key
继承interface B extends A { ... }
合并同名 interface 自动合并
vs type对象用 interface,联合/元组/工具用 type

动手练习 ​

  1. API 响应:定义 interface ApiResponse<T>,包含 code / message / data
  2. 嵌套接口:定义 User,包含 address: { city: string; zip: string }
  3. 继承练习:定义 Animal → Dog extends Animal(加 bark(): void)

下一章:第 6 章:类型别名与联合 →

本站基于 VitePress 构建 · 由 StackHub 团队维护