<返回目录     Powered by claud/xia兄

第3课: 接口Interface

什么是接口?

接口是TypeScript的核心概念之一,用于定义对象的结构和类型约束。接口只在编译时存在,不会出现在编译后的JavaScript代码中。

接口的核心作用:

接口与类型别名的区别

// 接口定义
interface User {
  name: string;
  age: number;
}

// 类型别名定义
type UserType = {
  name: string;
  age: number;
};

// 主要区别:
// 1. 接口可以被继承(extends),类型别名不能
// 2. 接口可以被实现(implements),类型别名不能
// 3. 接口支持声明合并,类型别名不支持
// 4. 类型别名更灵活,可以定义联合类型、交叉类型等

基本接口定义

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

function greet(person: Person) {
  console.log(`Hello, ${person.name}!`);
}

let user = { name: "Alice", age: 25 };
greet(user);

可选属性

使用 ? 标记可选属性:

interface Config {
  color?: string;
  width?: number;
}

function createSquare(config: Config): { color: string; area: number } {
  let newSquare = { color: "white", area: 100 };
  if (config.color) {
    newSquare.color = config.color;
  }
  if (config.width) {
    newSquare.area = config.width * config.width;
  }
  return newSquare;
}

let mySquare = createSquare({ color: "black" });

只读属性

使用 readonly 标记只读属性:

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

let p1: Point = { x: 10, y: 20 };
p1.x = 5; // 错误!x是只读的

// ReadonlyArray类型
let a: number[] = [1, 2, 3, 4];
let ro: ReadonlyArray = a;
ro[0] = 12; // 错误!
ro.push(5); // 错误!

函数类型接口

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

let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
  return source.search(subString) > -1;
};

可索引类型

// 数字索引
interface StringArray {
  [index: number]: string;
}

let myArray: StringArray = ["Bob", "Fred"];
let myStr: string = myArray[0];

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

let dict: StringDictionary = {
  name: "Alice",
  city: "Beijing"
};

类类型接口

interface ClockInterface {
  currentTime: Date;
  setTime(d: Date): void;
}

class Clock implements ClockInterface {
  currentTime: Date = new Date();
  setTime(d: Date) {
    this.currentTime = d;
  }
}

接口继承

interface Shape {
  color: string;
}

interface Square extends Shape {
  sideLength: number;
}

let square = {} as Square;
square.color = "blue";
square.sideLength = 10;

// 继承多个接口
interface PenStroke {
  penWidth: number;
}

interface SquareWithPen extends Shape, PenStroke {
  sideLength: number;
}

混合类型接口

一个对象可以同时作为函数和对象使用:

interface Counter {
  (start: number): string;
  interval: number;
  reset(): void;
}

function getCounter(): Counter {
  let counter = function(start: number) {} as Counter;
  counter.interval = 123;
  counter.reset = function() {};
  return counter;
}

let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;
接口 vs 类型别名:

接口可以被继承和实现,类型别名更灵活但不能被继承。通常优先使用接口定义对象结构。

练习:接口综合实践

练习1:基础接口定义

定义以下接口:

// 1. User接口:name(必填), email(必填), age(可选), isActive(布尔)
// 2. Product接口:id(只读), name, price, category(可选)
// 3. Order接口:id, userId, products(Product数组), totalAmount

练习2:函数类型接口

创建函数类型接口:

// 1. 比较函数接口:比较两个数字返回布尔值
// 2. 转换函数接口:将字符串转换为数字
// 3. 回调函数接口:处理异步操作结果

练习3:接口继承和组合

使用接口继承创建复杂类型:

// 1. 基础接口:Person(姓名, 年龄)
// 2. 扩展接口:Employee(继承Person,添加职位, 薪资)
// 3. 多重继承:Manager(继承Employee,添加部门, 下属列表)

练习4:实际应用场景

实现一个简单的用户管理系统:

// 1. 定义用户相关接口
// 2. 创建用户操作函数(添加、查询、更新、删除)
// 3. 确保类型安全,处理边界情况
// 4. 使用只读属性保护关键数据

练习5:接口高级特性

探索接口的高级用法:

// 1. 声明合并:定义同名接口的多个部分
// 2. 索引签名:处理动态属性
// 3. 混合类型:既是函数又是对象的接口
// 4. 泛型接口:创建可重用的接口模板

总结

在本课中,我们深入学习了TypeScript接口的核心概念:

关键知识点回顾: