介绍
type
类型别名,可以给一个类型起一个新名称。它不会新建一个类型,只是创建了新名称来引用那个类型。
type name = string;
type txt = 'hello' | 'world';
function sayIt(name: name) {
// 错误示例1
// const word: txt = 'hell';
// 会报错提示:
// const word: txt
// 不能将类型“"hell"”分配给类型“txt”
const word: txt = 'hello';
console.log(word);
}
// 错误示例2
// sayIt(234);
// 会报错提示:
// 类型“number”的参数不能赋给类型“string”的参数。
sayIt('hali');
interface
描述和检查对象的数据结构以及值类型。
interface Example {
txt: string;
count: number
}
function example(props: Example) {
console.log(props);
}
// 错误示例:
// example({ txt: 12, count: 100 });
// 会报错提示:
// (property) Example.count: number
// 不能将类型“number”分配给类型“string”。
example({txt: 'hello', count: 100});
相同点
不管是 type 还是 interface 都可以用来约束值类型。
区别
-
interface会新建一个名称,可以在任何其他地方使用,类型错误提示中也会显示对应的名称(请看 介绍章节的interface代码中的错误示例 )。而type不会新创建名字(因为只是给类型起了一个别名而已),所以在值类型错误的时候,错误提示并不会显示对应的名称,而是直接显示了对应的类型的字面量(请看 介绍章节的type代码中的错误示例 )。 -
interface会自动合并相同名称的的值类型约束内容,但相同名称的type会报错interface Example { txt: string } interface Example { count: number } const example: Example = { txt: '123', count: 123 } // 报错:标识符“name”重复。 type name = string; type name = number; -
interface可以使用extends和implments,而type不可以。实现(implements)是面向对象中的一个重要概念。一般来讲,一个类只能继承自另一个类,有时候不同类之间可以有一些共有的特性,这时候就可以把特性提取成接口(interfaces),用
implements关键字来实现。这个特性大大提高了面向对象的灵活性。// https://ts.xcatliu.com/advanced/class-and-interfaces.html // 举例来说,门是一个类,防盗门是门的子类。如果防盗门有一个报警器的功能,我们可以简单的给防盗门添加一个报警方法。这时候如果有另一个类,车,也有报警器的功能,就可以考虑把报警器提取出来,作为一个接口,防盗门和车都去实现它: interface Alarm { alert(): void; } interface Light { lightOn(): void; lightOff(): void; } class Car implements Alarm, Light { alert() { console.log('Car alert'); } lightOn() { console.log('Car light on'); } lightOff() { console.log('Car light off'); } } -
type可以实现值类型约束的并集和交集,而interface不可以。type ExampleA = { name: string }; type ExampleB = { age: number }; type ExampleC = ExampleA & ExampleB; type ExampleD = ExampleA | ExampleB; // 缺一不可 const exampleC: ExampleC = { name: 'hello', age: 123 } // 全缺不可 const exampleD: ExampleD = { name: 'world', age: 123 } // interface 也可以作为交集和并集子项 interface ExampleE { name: string } interface ExampleF { age: number } type ExampleG = ExampleE & ExampleF; type ExampleH = ExampleE | ExampleF; // 缺一不可 const exampleG: ExampleG = { name: 'hello', age: 456 } // 全缺不可 const exampleH: ExampleH = { name: 'hello', age: 456 } -
type可以声明元组(Tuples),而interface不可以。type Example = [string, number]; // 但 interface 中可以使用元组 interface ExampleA = { value: [string, number] }
总结
- 要始终记得
type是类型别名,interface是接口,名字突出意义; - 一般情况下,两者都可以用来约束值类型;
- 特殊情况,如这个值约束的集合可能会被多处使用(如继承,实现)或可能有同名的但约束的值不同或值类型不同的话,就只能选择
interface了; - 特殊情况下,如果是声明元组或实现一个灵活的值类型集合的交叉或合并的时候,
type就可以大展身手了; - 两者混合食用,味道更佳。