接口是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;
接口可以被继承和实现,类型别名更灵活但不能被继承。通常优先使用接口定义对象结构。
定义以下接口:
// 1. User接口:name(必填), email(必填), age(可选), isActive(布尔)
// 2. Product接口:id(只读), name, price, category(可选)
// 3. Order接口:id, userId, products(Product数组), totalAmount
创建函数类型接口:
// 1. 比较函数接口:比较两个数字返回布尔值
// 2. 转换函数接口:将字符串转换为数字
// 3. 回调函数接口:处理异步操作结果
使用接口继承创建复杂类型:
// 1. 基础接口:Person(姓名, 年龄)
// 2. 扩展接口:Employee(继承Person,添加职位, 薪资)
// 3. 多重继承:Manager(继承Employee,添加部门, 下属列表)
实现一个简单的用户管理系统:
// 1. 定义用户相关接口
// 2. 创建用户操作函数(添加、查询、更新、删除)
// 3. 确保类型安全,处理边界情况
// 4. 使用只读属性保护关键数据
探索接口的高级用法:
// 1. 声明合并:定义同名接口的多个部分
// 2. 索引签名:处理动态属性
// 3. 混合类型:既是函数又是对象的接口
// 4. 泛型接口:创建可重用的接口模板
在本课中,我们深入学习了TypeScript接口的核心概念: