interface
在 TypeScript 中,接口(
interface
)用于定义对象的结构类型。接口是一个关键的概念,它帮助你定义对象的类型和形状,从而使代码更易于理解和维护。下面详细介绍 TypeScript 接口的作用、核心原则、类型、实现、继承及一些注意事项。
1. 接口的作用
接口的主要作用是定义对象的类型。它描述了对象应该具有的属性和方法。接口不会在编译后的 JavaScript 中生成代码,仅在编译时进行类型检查。
2. 核心原则
TypeScript 的核心原则是基于结构类型系统,即类型是基于其成员来定义的。接口描述了一个对象的形状,并且是面向类型检查的契约。
3. 定义和使用接口
基本接口
interface Person {
firstName: string;
lastName: string;
age?: number; // 可选属性
}
function greet(person: Person) {
console.log(`Hello, ${person.firstName} ${person.lastName}`);
}
let user = { firstName: 'John', lastName: 'Doe' };
greet(user); // 输出: Hello, John Doe
4. 接口中的属性和方法
接口不仅可以描述对象的属性,还可以描述对象的方法。
interface Person {
firstName: string;
lastName: string;
sayHello(): string; // 方法
}
let user: Person = {
firstName: 'John',
lastName: 'Doe',
sayHello: function () {
return `Hello, ${this.firstName} ${this.lastName}`;
},
};
console.log(user.sayHello()); // 输出: Hello, John Doe
5. 接口的可选属性和只读属性
可选属性
接口中的可选属性使用 ?
标记。
interface Person {
firstName: string;
lastName: string;
age?: number; // 可选属性
}
只读属性
接口中的只读属性使用 readonly
标记,表示属性不可修改。
interface Point {
readonly x: number;
readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
// p1.x = 5; // 错误: 不能修改只读属性
6. 接口的继承
接口可以通过 extends
关键字继承其他接口,从而实现接口的扩展。
interface Named {
name: string;
}
interface Person extends Named {
age: number;
}
let person: Person = {
name: 'Alice',
age: 25,
};
console.log(person.name); // 输出: Alice
console.log(person.age); // 输出: 25
7. 混合类型接口
接口可以描述具有多种类型的对象,例如既有属性又有方法的对象。
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
let counter = <Counter>function (start: number) {
console.log(`Counter started at ${start}`);
};
counter.interval = 123;
counter.reset = function () {
console.log('Counter reset');
};
return counter;
}
let c = getCounter();
c(10); // 输出: Counter started at 10
c.interval = 5;
c.reset(); // 输出: Counter reset
8. 实现接口
类可以实现一个接口,用 implements
关键字。
interface Person {
firstName: string;
lastName: string;
}
class Employee implements Person {
firstName: string;
lastName: string;
constructor(firstName: string, lastName: string) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName(): string {
return `${this.firstName} ${this.lastName}`;
}
}
let employee = new Employee('John', 'Doe');
console.log(employee.getFullName()); // 输出: John Doe
9. 接口与类型别名
虽然接口和类型别名(type alias
)都可以定义对象类型,但接口更适合用于描述对象的结构和行为,而类型别名更适合用于组合简单类型或联合类型。
type Point = {
x: number;
y: number;
};
interface Rectangle {
width: number;
height: number;
}
interface ColoredRectangle extends Rectangle {
color: string;
}
let rect: ColoredRectangle = {
width: 10,
height: 20,
color: 'blue',
};
10. 注意事项
- 接口合并:在 TypeScript 中,接口可以自动合并,这在声明全局类型时非常有用。
interface Box { height: number; width: number; } interface Box { scale: number; } let box: Box = { height: 5, width: 6, scale: 10 };
- 可选属性检查:当使用可选属性时,要注意检查该属性是否存在。
interface Person { firstName: string; lastName: string; age?: number; } function printAge(person: Person) { if (person.age !== undefined) { console.log(`Age: ${person.age}`); } }
- 严格类型检查:在严格模式下,TypeScript 会对接口进行严格的类型检查,这有助于捕捉潜在的错误。
readonly vs const
在 TypeScript 中,readonly
和 const
都用于创建不可修改的值,但它们应用的场景有所不同,具体区别如下:
readonly
readonly
用于属性级别,用来表示一个属性只读,即不能修改其值。
对象属性中的使用:
interface Person {
readonly name: string;
age: number;
}
let person: Person = { name: 'Alice', age: 30 };
person.age = 25; // 可以修改 age 属性
// person.name = "Bob"; // 错误: 无法分配到 "name" ,因为它是只读的属性。
类中的使用:
class MyClass {
readonly x: number;
constructor(x: number) {
this.x = x;
}
}
let myObject = new MyClass(10);
console.log(myObject.x); // 输出: 10
// myObject.x = 20; // 错误: 无法分配到 "x" ,因为它是只读的属性。
const
const
用于变量声明,表示一个常量,一旦声明,其值不能重新赋值。
变量声明中的使用:
const PI = 3.14;
// PI = 3.14159; // 错误: 无法重新分配 "PI" ,因为它是常数。
区别:
- 作用范围:
readonly
可以用于对象的属性以及类的属性,表示属性只读。const
只能用于变量的声明,表示变量的值只读。
- 赋值时机:
readonly
的值可以在运行时或构造函数中赋值。const
的值必须在声明时立即赋值,并且不能再次赋值。
- 使用场景:
- 如果需要将一个属性标记为不可修改,应该使用
readonly
。 - 如果需要声明一个常量值,应该使用
const
。
- 如果需要将一个属性标记为不可修改,应该使用
在实际使用中,根据变量或属性的需要确定是使用 readonly
还是 const
是很重要的。
总结
TypeScript 的接口是一种强大的工具,用于定义对象的结构类型、确保类型安全、实现面向对象编程的抽象和继承。通过使用接口,可以编写更可读、可维护的代码,并提高开发效率。希望这些示例和注意事项能帮助你更好地理解和使用 TypeScript 的接口。