MST

星途 面试题库

面试题:TypeScript 中类的结构化类型与接口的关系

在 TypeScript 里,阐述类的结构化类型与接口在实现和应用场景上的主要区别,并举例说明在哪些情况下会优先选择使用类的结构化类型而非接口。
14.9万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

实现区别

  1. 类的结构化类型:基于对象的实际结构进行类型检查,无需显式声明实现某个特定结构,只要对象具有相应的属性和方法即可。例如:
class Animal {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    speak() {
        console.log(`${this.name} makes a sound.`);
    }
}

class Dog {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    speak() {
        console.log(`${this.name} barks.`);
    }
}

function greet(animal: { name: string; speak(): void }) {
    animal.speak();
}

const myDog = new Dog('Buddy');
greet(myDog); 

这里Dog类并没有显式声明实现某个接口,但由于其结构与greet函数参数期望的结构匹配,所以可以正常使用。 2. 接口:需要类显式声明实现接口,明确表明类满足接口定义的结构。例如:

interface AnimalInterface {
    name: string;
    speak(): void;
}

class Cat implements AnimalInterface {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    speak() {
        console.log(`${this.name} meows.`);
    }
}

Cat类通过implements关键字明确表明实现了AnimalInterface接口。

应用场景区别

  1. 类的结构化类型:适用于更灵活、动态的类型匹配场景,不需要严格的继承或实现关系,只关注对象的实际结构。比如在函数参数类型定义上,当我们只关心传入对象是否具有某些属性和方法,而不关心其具体类时,可使用结构化类型。像上述greet函数,不管是Animal类还是Dog类的实例,只要结构匹配就能传入。
  2. 接口:适用于需要明确契约和类型约束的场景,确保类具有特定的结构。常用于多个类需要遵循相同结构的情况,比如在大型项目中,不同模块的类可能需要实现相同接口以保证一致性。

优先选择类的结构化类型的情况

  1. 临时或一次性的类型匹配:当在某个局部函数中,只需要对传入对象的结构进行简单验证,而不需要定义一个正式的接口时,使用结构化类型更便捷。例如:
function printDetails(obj: { title: string; content: string }) {
    console.log(`Title: ${obj.title}, Content: ${obj.content}`);
}

const article = { title: 'New Article', content: 'This is the content...' };
printDetails(article); 

这里没有必要为这种一次性使用的结构定义接口。 2. 处理来自外部库且难以或无需定义接口的对象:当使用一些外部库返回的对象,其结构明确但不适合定义接口时,结构化类型可直接使用。比如某些第三方 API 返回的数据对象,我们只关心其特定的属性结构来进行处理,而不是为其专门定义接口。