1. 泛型约束
- interface:接口在泛型约束时,主要通过在接口定义中声明类型参数来约束。例如:
interface KeyValuePair<TKey, TValue> {
key: TKey;
value: TValue;
}
function getValue<K, V>(pair: KeyValuePair<K, V>): V {
return pair.value;
}
- type:类型别名在泛型约束时同样声明类型参数。例如:
type KeyValuePair<TKey, TValue> = {
key: TKey;
value: TValue;
};
function getValue<K, V>(pair: KeyValuePair<K, V>): V {
return pair.value;
}
- 差异:在泛型约束方面,二者基本行为一致,都能很好地实现对泛型类型的约束。选择上可基于个人喜好或团队习惯,若注重面向对象风格,interface 稍显直观;若追求简洁表达,type 更合适。
2. 条件类型
- interface:接口本身不能直接定义条件类型。因为接口旨在定义结构,而条件类型是根据条件动态生成类型。
- type:类型别名可以方便地定义条件类型。例如:
type IsString<T> = T extends string ? true : false;
type StringCheck = IsString<string>; // true
type NumberCheck = IsString<number>; // false
- 差异:在条件类型场景下,type 具有明显优势,能够灵活地根据不同条件生成不同类型,interface 则无法胜任。所以当需要根据条件动态生成类型时,应选择 type。
3. 映射类型
- interface:接口不能直接定义映射类型。接口的定义方式是固定结构的声明,不支持像映射类型那样对已有类型进行变换。
- type:类型别名可以轻松定义映射类型。例如:
type User = {
name: string;
age: number;
};
type ReadonlyUser = {
readonly [P in keyof User]: User[P];
};
let readonlyUser: ReadonlyUser = { name: 'John', age: 30 };
// readonlyUser.name = 'Jane'; // 报错,只读属性不能重新赋值
- 差异:在映射类型方面,type 能够实现对已有类型的属性进行遍历、变换等操作,而 interface 不具备此能力。所以当需要对类型的属性进行映射变换时,type 是唯一选择。
总结
- 若只是定义简单的泛型结构,interface 和 type 均可,可依个人或团队风格选择。
- 当涉及条件类型或映射类型等复杂类型操作时,应优先选择 type,以提高代码的可读性与可维护性,因为 type 在这些场景下功能更强大且表达更简洁。