MST

星途 面试题库

面试题:TypeScript接口与类型别名在泛型使用场景下的特性差异

在泛型编程中,TypeScript的接口和类型别名都有各自的特性。请举例说明在泛型约束、泛型扩展等场景下,接口和类型别名表现出的不同之处,并解释原因。
38.2万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

泛型约束场景

  • 接口
interface KeyValuePair<TKey, TValue> {
    key: TKey;
    value: TValue;
}
function getValue<TKey, TValue>(pair: KeyValuePair<TKey, TValue>): TValue {
    return pair.value;
}

接口定义了一种契约,明确了对象的结构。在泛型约束场景下,通过接口来约束对象结构非常直观,适用于对象形状明确且固定的情况。

  • 类型别名
type KeyValuePairAlias<TKey, TValue> = {
    key: TKey;
    value: TValue;
};
function getValueAlias<TKey, TValue>(pair: KeyValuePairAlias<TKey, TValue>): TValue {
    return pair.value;
}

类型别名在泛型约束场景下同样可以很好地定义对象结构,与接口类似。然而,接口在定义对象类型方面更具传统的面向对象风格,而类型别名则更为灵活,还可以用于其他类型如联合类型、交叉类型等的定义。

泛型扩展场景

  • 接口
interface Animal {
    name: string;
}
interface Dog extends Animal {
    bark(): void;
}
interface Box<T> {
    value: T;
}
interface DogBox extends Box<Dog> {
    playWithDog(): void;
}

接口可以通过extends关键字方便地实现扩展。在泛型扩展场景下,接口能清晰地表达类型之间的继承关系,便于构建复杂的类型层次结构,这符合面向对象编程中对类型继承和层次化设计的理念。

  • 类型别名
type AnimalAlias = {
    name: string;
};
type DogAlias = AnimalAlias & {
    bark(): void;
};
type BoxAlias<T> = {
    value: T;
};
type DogBoxAlias = BoxAlias<DogAlias> & {
    playWithDog(): void;
};

类型别名通过交叉类型&来实现类似的扩展效果。但相比之下,接口的extends语法更直观地体现继承关系,而类型别名的交叉类型语法在表达复杂继承关系时可能会略显冗长,尤其是当涉及多层扩展时。

总体来说,接口在面向对象风格的类型定义和扩展上表现出色,适合构建清晰的类型层次结构;而类型别名更灵活,不仅能定义对象类型,还能方便地处理联合类型、交叉类型等复杂类型,但在表达继承关系上不如接口直观。