TypeScript 接口

TypeScript 中的接口(Interface)详解

接口(interface) 是 TypeScript 中最常用、最重要的类型定义方式之一,主要用于描述对象的形状(shape),定义对象应该具有哪些属性、方法及其类型。它是 TypeScript 类型系统的核心,帮助实现结构化类型检查(structural typing)。

1. 基本用法:定义对象形状

interface Person {
  name: string;
  age: number;
}

let user: Person = {
  name: "Alice",
  age: 30
};

// user = { name: "Bob" };              // 错误:缺少 age 属性
// user = { name: "Charlie", age: "25" }; // 错误:age 必须是 number

TypeScript 是结构化类型系统:只要对象满足接口要求的形状,即使没有显式声明 implements,也能赋值。

let admin = { name: "Eve", age: 28, role: "admin" };  // 多余属性 role
let p: Person = admin;  // OK!TypeScript 允许额外属性(新鲜度检查例外情况见后文)

2. 可选属性(Optional Properties)

使用 ? 表示属性可选:

interface Book {
  title: string;
  author: string;
  pages?: number;     // 可选
  readonly isbn: string;  // 只读(见下文)
}

let novel: Book = {
  title: "1984",
  author: "Orwell",
  isbn: "978-0141036144"
  // pages 可省略
};

3. 只读属性(Readonly Properties)

使用 readonly 防止属性被修改:

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

let origin: Point = { x: 0, y: 0 };
// origin.x = 10;  // 错误:只读
  • 只读数组:readonly string[]ReadonlyArray<string>
let names: readonly string[] = ["Alice", "Bob"];
// names.push("Charlie");  // 错误

4. 函数类型(Function Types)

接口可以描述函数形状:

interface SearchFunc {
  (source: string, subString: string): boolean;
}

let mySearch: SearchFunc = function(src, sub) {
  return src.includes(sub);
};

mySearch("hello", "ell");  // true

5. 索引签名(Index Signatures)

允许动态属性名:

interface StringDictionary {
  [key: string]: string;  // 键为 string,值为 string
  length: number;         // 固定属性必须兼容索引签名类型
}

let dict: StringDictionary = {
  name: "Alice",
  job: "Engineer",
  length: 2               // OK,number 可赋值给 string(宽松规则)
};
  • 也可以是 number 索引:[index: number]: string

6. 接口继承(Extends)

接口可以继承一个或多个接口:

interface Animal {
  name: string;
}

interface Dog extends Animal {
  breed: string;
  bark(): void;
}

let dog: Dog = {
  name: "Buddy",
  breed: "Golden Retriever",
  bark() { console.log("Woof!"); }
};

多继承:

interface Flyable {
  fly(): void;
}

interface Swimmable {
  swim(): void;
}

interface Duck extends Animal, Flyable, Swimmable {
  quack(): void;
}

7. 接口 vs 类型别名(type)

特性interfacetype alias
定义对象形状推荐可行
联合类型 / 字面量类型不支持支持
原始类型映射不支持支持(如 type Id = string | number
可重复声明(声明合并)支持(同名接口会合并)不支持
实现类(implements)支持不支持(class 只能 implements interface)
扩展方式extends&(交叉类型)

推荐

  • 定义对象/函数形状 → 用 interface
  • 需要联合、映射、条件类型 → 用 type

8. 声明合并(Declaration Merging)

同名接口会自动合并(非常有用,如扩展第三方库):

interface User {
  name: string;
}

interface User {
  age: number;
}

// 等价于:
interface User {
  name: string;
  age: number;
}

let u: User = { name: "Tom", age: 25 };

常用于扩展全局对象第三方库类型

9. 混合类型(Hybrid Types)

接口可以同时描述对象和函数(少见但强大):

interface Counter {
  (start: number): string;  // 作为函数
  count: number;            // 属性
  reset(): void;            // 方法
}

let counter: Counter = (() => {
  let c = 0;
  let fn = function(start: number) {
    c = start;
    return `Count: ${c}`;
  };
  fn.count = c;
  fn.reset = () => { c = 0; };
  return fn as Counter;
})();

10. 最佳实践建议

建议说明
对象形状优先用 interface可读性强,支持声明合并
可选属性放后面保持一致性
只读属性用于不可变数据如 ID、配置
函数类型复杂时用 interface(params) => return 更清晰
扩展第三方库时用 interface利用声明合并
开启 "strict": true包括 strictPropertyInitialization

小结:接口速查表

特性语法示例
基本接口interface Person { name: string; age: number; }
可选属性pages?: number;
只读属性readonly id: number;
函数属性greet(name: string): void;
索引签名[prop: string]: any;
继承interface Admin extends Person { role: string; }
函数类型接口interface Fn { (x: number): string; }

接口是 TypeScript 中定义对象合约的最优雅方式,结合继承、声明合并等特性,能极大提升大型项目的类型安全和可维护性。

如果您想深入了解类实现接口(implements)接口与抽象类的区别工具类型(如 Partial、Pick)与接口结合,或者需要实际项目示例,请告诉我!

文章已创建 3383

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部