TypeScript接口知识详解
编程小白也能理解的TypeScript核心概念指南
接口(Interface)是TypeScript中最重要的概念之一,它就像一份”合同”,定义了对象应该长什么样子,包含哪些属性和方法。
1. 接口是什么?
接口可以理解为一份”形状说明书”,它定义了一个对象必须包含哪些属性和方法。
想象你去定制一件衣服,你会告诉裁缝:
- 需要什么材质
- 什么颜色
- 袖口样式
- 口袋数量
接口的作用类似:它告诉TypeScript某个对象必须包含哪些属性,每个属性是什么类型。
interface Person {
name: string;
age: number;
}
// 使用接口
let user: Person = {
name: “张三”,
age: 30
};
name: string;
age: number;
}
// 使用接口
let user: Person = {
name: “张三”,
age: 30
};
2. 接口的基本用法
接口最简单的用法就是定义对象的形状:
// 定义Book接口
interface Book {
title: string;
author: string;
price: number;
}
// 创建符合Book接口的对象
let myBook: Book = {
title: “TypeScript入门”,
author: “李四”,
price: 49.9
};
// 如果缺少属性,TypeScript会报错
let wrongBook: Book = {
title: “错误的书”,
author: “王五”
}; // 错误:缺少price属性
interface Book {
title: string;
author: string;
price: number;
}
// 创建符合Book接口的对象
let myBook: Book = {
title: “TypeScript入门”,
author: “李四”,
price: 49.9
};
// 如果缺少属性,TypeScript会报错
let wrongBook: Book = {
title: “错误的书”,
author: “王五”
}; // 错误:缺少price属性
3. 可选属性:可有可无的属性
有些属性不是必须的,就像手机可以有多种颜色,但不是必须指定颜色。
interface Phone {
brand: string;
model: string;
color?: string; // 问号表示可选
}
// 可以不带color属性
let phone1: Phone = {
brand: “华为”,
model: “P50”
};
// 也可以带上color属性
let phone2: Phone = {
brand: “苹果”,
model: “iPhone 13”,
color: “蓝色”
};
brand: string;
model: string;
color?: string; // 问号表示可选
}
// 可以不带color属性
let phone1: Phone = {
brand: “华为”,
model: “P50”
};
// 也可以带上color属性
let phone2: Phone = {
brand: “苹果”,
model: “iPhone 13”,
color: “蓝色”
};
4. 只读属性:初始化后不能修改
就像身份证号,一旦确定就不能更改。
interface Student {
readonly id: number; // readonly表示只读
name: string;
grade: number;
}
let student: Student = {
id: 1001,
name: “小明”,
grade: 3
};
student.name = “小红”; // 允许修改
student.id = 1002; // 错误!id是只读的
readonly id: number; // readonly表示只读
name: string;
grade: number;
}
let student: Student = {
id: 1001,
name: “小明”,
grade: 3
};
student.name = “小红”; // 允许修改
student.id = 1002; // 错误!id是只读的
5. 函数类型:描述函数的样子
接口不仅可以描述对象,还可以描述函数应该是什么样子。
// 定义一个函数接口
interface SearchFunc {
(source: string, keyword: string): boolean;
}
// 使用函数接口
let mySearch: SearchFunc;
mySearch = function(src: string, kw: string): boolean {
return src.indexOf(kw) > -1;
};
interface SearchFunc {
(source: string, keyword: string): boolean;
}
// 使用函数接口
let mySearch: SearchFunc;
mySearch = function(src: string, kw: string): boolean {
return src.indexOf(kw) > -1;
};
提示: 函数参数名不需要和接口定义完全一致,只要类型匹配即可
6. 可索引类型:描述数组和字典
当对象有不确定数量的属性时(如数组、字典),可以使用索引类型。
数组示例:
interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = [“北京”, “上海”];
let city: string = myArray[0]; // 北京
[index: number]: string;
}
let myArray: StringArray;
myArray = [“北京”, “上海”];
let city: string = myArray[0]; // 北京
字典示例:
interface NumberDictionary {
[key: string]: number;
}
let scores: NumberDictionary = {
“语文”: 95,
“数学”: 87
};
let mathScore: number = scores[“数学”]; // 87
[key: string]: number;
}
let scores: NumberDictionary = {
“语文”: 95,
“数学”: 87
};
let mathScore: number = scores[“数学”]; // 87
7. 类类型:类实现接口
类(class)可以实现(implements)接口,就像承诺”我会按照接口的要求来实现”。
interface ClockInterface {
currentTime: Date;
setTime(d: Date): void;
}
// 类实现接口
class Clock implements ClockInterface {
currentTime: Date = new Date();
setTime(d: Date) {
this.currentTime = d;
}
// 还可以添加其他方法
getTime(): string {
return this.currentTime.toLocaleTimeString();
}
}
currentTime: Date;
setTime(d: Date): void;
}
// 类实现接口
class Clock implements ClockInterface {
currentTime: Date = new Date();
setTime(d: Date) {
this.currentTime = d;
}
// 还可以添加其他方法
getTime(): string {
return this.currentTime.toLocaleTimeString();
}
}
注意: 类实现接口时,必须包含接口中定义的所有属性和方法
8. 接口继承:扩展接口
接口可以继承其他接口,就像孩子继承父母的特性。
interface Shape {
color: string;
}
// Square接口继承Shape接口
interface Square extends Shape {
sideLength: number;
}
let square = {} as Square;
square.color = “blue”; // 来自Shape
square.sideLength = 10; // 来自Square
color: string;
}
// Square接口继承Shape接口
interface Square extends Shape {
sideLength: number;
}
let square = {} as Square;
square.color = “blue”; // 来自Shape
square.sideLength = 10; // 来自Square
9. 混合类型:多种类型组合
一个接口可以同时描述多种类型,比如既是对象又有函数特性。
interface Counter {
// 函数特性
(start: number): string;
// 对象特性
interval: number;
reset(): void;
}
function getCounter(): Counter {
let counter = function (start: number) {} as Counter;
counter.interval = 5;
counter.reset = function () {};
return counter;
}
// 函数特性
(start: number): string;
// 对象特性
interval: number;
reset(): void;
}
function getCounter(): Counter {
let counter = function (start: number) {} as Counter;
counter.interval = 5;
counter.reset = function () {};
return counter;
}
10. 接口继承类
接口可以继承类的结构,但不包含实现。
class Control {
state: any;
}
interface SelectableControl extends Control {
select(): void;
}
// 实现接口的类必须也继承Control
class Button extends Control implements SelectableControl {
select() { }
}
state: any;
}
interface SelectableControl extends Control {
select(): void;
}
// 实现接口的类必须也继承Control
class Button extends Control implements SelectableControl {
select() { }
}
11. 使用接口的注意事项
接口是TypeScript的核心概念,但使用时有几个重要事项需要注意:
- 接口不会出现在编译后的JavaScript代码中 – 它们只是开发时的类型检查工具
- 一个类可以实现多个接口 – 用逗号分隔
- 接口可以继承多个接口 – 使用extends关键字,多个接口用逗号分隔
- 接口不能实例化 – 不能使用new创建接口实例
- 接口可以描述TypeScript支持的任何类型 – 包括原始值、对象、函数、类等
// 实现多个接口
interface A { a: number }
interface B { b: string }
class C implements A, B {
a: number = 1;
b: string = “hello”;
}
// 继承多个接口
interface D extends A, B {
c: boolean;
}
interface A { a: number }
interface B { b: string }
class C implements A, B {
a: number = 1;
b: string = “hello”;
}
// 继承多个接口
interface D extends A, B {
c: boolean;
}
接口知识总结
接口是TypeScript中最重要的概念之一,它定义了代码的”形状”(结构)。使用接口可以:
- 为对象定义结构
- 定义函数签名
- 描述数组和字典
- 约束类的实现
- 组合和扩展类型
掌握接口的使用,可以让你写出更健壮、可维护性更好的TypeScript代码!