VVLL.net

Interface(接口)

日期:2024-08-22 09:58:31

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. 注意事项

  1. 接口合并:在 TypeScript 中,接口可以自动合并,这在声明全局类型时非常有用。
    interface Box {
      height: number;
      width: number;
    }
    
    interface Box {
      scale: number;
    }
    
    let box: Box = { height: 5, width: 6, scale: 10 };
    
  2. 可选属性检查:当使用可选属性时,要注意检查该属性是否存在。
    interface Person {
      firstName: string;
      lastName: string;
      age?: number;
    }
    
    function printAge(person: Person) {
      if (person.age !== undefined) {
        console.log(`Age: ${person.age}`);
      }
    }
    
  3. 严格类型检查:在严格模式下,TypeScript 会对接口进行严格的类型检查,这有助于捕捉潜在的错误。

readonly vs const

在 TypeScript 中,readonlyconst 都用于创建不可修改的值,但它们应用的场景有所不同,具体区别如下:

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" ,因为它是常数。

区别:

  1. 作用范围
    • readonly 可以用于对象的属性以及类的属性,表示属性只读。
    • const 只能用于变量的声明,表示变量的值只读。
  2. 赋值时机
    • readonly 的值可以在运行时或构造函数中赋值。
    • const 的值必须在声明时立即赋值,并且不能再次赋值。
  3. 使用场景
    • 如果需要将一个属性标记为不可修改,应该使用 readonly
    • 如果需要声明一个常量值,应该使用 const

在实际使用中,根据变量或属性的需要确定是使用 readonly 还是 const 是很重要的。

总结

TypeScript 的接口是一种强大的工具,用于定义对象的结构类型、确保类型安全、实现面向对象编程的抽象和继承。通过使用接口,可以编写更可读、可维护的代码,并提高开发效率。希望这些示例和注意事项能帮助你更好地理解和使用 TypeScript 的接口。

参考

标签