在typeScript中,“interface”和“type”都是用来定义自定义类型的关键字,他们在以下差异,用法上的一些区别(欢迎大家继续补充……)
1. 语法差异:
-
'interface’使用关键字’interface’定义,例如:interface Person { name: string; }
-
'type’使用关键字’type’定义,例如:type Person = { name: string; }
2.声明合并(Merging)的能力:
- 'interface’具有声明合并的能力,允许多个同名的接口进行合并,通过这样的方式可以扩展接口的成员定义。
- 'type’不具备声明合并的能力,多次定义同一个类型会报错
3.可扩展性:
- 'interface’可以使用关键字’extends’继承另一个接口,实现接口的复用和扩展。
- 'type’可以使用交叉类型(Intersection Types)进行复用和扩展,但不能使用extends关键字继承。
兼容性:
4.兼容性:
- 'interface’在进行类型兼容性检查时,会进行"兼容性递归检查",只要目标类型满足源类型的成员要求,就认为类型兼容。
- 'type’没有进行"兼容性递归检查",只有精确匹配才被认为是兼容。
类型注解和类型别名:
5.类型注解和类型别名:
- 'interface’可以用于定义函数类型、类类型等复杂类型的注解。
- 'type’可以用于定义任意类型的别名,可以简化复杂类型的书写。
6.访问修饰符:
- 'interface’可以在属性和方法上使用公共(public),私有(private)和受保护(protected)等访问修饰符。
- 'type’不能指定访问修饰符,它假定所有成员都是公共的。
7.联合类型与交叉类型:
- 'type’可以使用联合类型(Union Types)和交叉类型(Intersection Types)来组合多个类型。
- 'interface’没有直接支持联合类型和交叉类型的语法,但可以通过继承和声明合并的方式实现类似的效果。
8.实现接口和类型别名:
- 'interface’可以被类实现(implements)来强制约束类的结构。
- 'type’不能直接被类实现,它更适合作为类型别名来简化复杂类型的定义。
9.映射类型:
- 'type’可以使用映射类型来根据已有类型生成新的类型。
- 'interface’不支持映射类型。
type Options<T> = {
[K in keyof T]: boolean;
};
interface PersonOptions {
name: boolean;
age: boolean;
}
// 使用映射类型
type Result = Options<PersonOptions>;
// Result 的类型为 { name: boolean, age: boolean }
// 不能使用映射类型
// interface ResultInterface extends Options<PersonOptions> {}
10.范型参数位置:
- 在范型参数位置上,'type’可以出现在任意位置,且可以交叉和联合多个类型。
- 在范型参数位置上,'interface’只能出现在类型别名的右侧。
type Tuple = [number, string];
type NumberArray = Array<number>;
type Union = number | string;
// 有效的定义
type MyType<T> = { value: T };
type MyType2 = MyType<number>;
// 有效的定义
interface MyInterface<T> {
value: T;
}
type MyInterface2 = MyInterface<number>;
// 无效的定义
// interface MyInterface<T> {
// value: T;
// }
// interface MyInterface2 extends MyInterface<number> {}
11.扩展对象类型:
- 'interface’可以通过声明合并的方式扩展已有的对象类型,从而添加新的属性或方法。
- 'type’需要使用交叉类型来实现对象类型的扩展。
interface Person {
name: string;
}
interface ExtendedPerson extends Person {
age: number;
}
// 使用声明合并进行扩展
const person: ExtendedPerson = {
name: 'John',
age: 25,
};
type Person = {
name: string;
};
type ExtendedPerson = Person & {
age: number;
};
// 使用交叉类型进行扩展
const person: ExtendedPerson = {
name: 'John',
age: 25,
};
12.调用签名和构造函数:
- 'interface’可以定义调用签名来描述函数类型,也可以定义构造函数签名来描述类的构造函数。
- 'type’可以使用函数类型和构造函数类型别名来描述函数类型和类的构造函数。
interface Greeting {
(name: string): string;
}
interface Person {
new (name: string): Person;
name: string;
sayHello(): void;
}
// 定义调用签名和构造函数签名
const greeting: Greeting = (name) => `Hello, ${name}!`;
class PersonClass implements Person {
constructor(public name: string) {}
sayHello() {
console.log(`Hello, my name is ${this.name}.`);
}
}
type Greeting = (name: string) => string;
type Person = {
new (name: string): Person;
name: string;
sayHello(): void;
};
// 使用类型别名
const greeting: Greeting = (name) => `Hello, ${name}!`;
class PersonClass implements Person {
constructor(public name: string) {}
sayHello() {
console.log(`Hello, my name is ${this.name}.`);
}
}