我可以使用接口和类型别名来做大多数相同的事情。
例如
类可以实现接口或键入别名
interface Shape {
area(): number;
}
type Perimeter = {
perimeter(): number;
}
class Rectangle implements Shape, Perimeter {
}
可以将它们组合以创建新的接口/类型别名
interface A {
a: string;
}
type B = {
b: string
}
interface C extends B {
c: string;
}
type D = A & {
d: string;
}
接口和类型注释之间是否存在语义差异?
答案 0 :(得分:1)
接口可以扩展其他接口,也可以*实现类。接口也可以利用declaration merging:
type A = {
a: string;
}
type A = { // <-- error: duplicate identifier A
b: string;
}
interface A {
a: string;
}
interface A { // <-- okay, A is { a: string, b: string }
b: string;
}
编辑:已更改为*实现
edit 2:相交与延伸不同。请考虑以下内容:
interface A {
num: number;
str: string;
}
type B = A & { // <-- this is okay, but overwrites the num property type to number & string
arr: any[];
num: string;
}
interface C extends A { // <-- error: C incorrectly extends A
num: string;
}
编辑3:对于某些人来说,另一个潜在的重大差异(虽然不一定是语义差异)是类型在工具提示中枚举(至少在vscode中),而接口则没有。
答案 1 :(得分:0)
interface
和type
之间的技术差异为well-described here。
但是,对于同时使用type
和interface
的情况,根本没有语义上的差异。
interface
继承和type
交集在TypeScript中,接口之间的层次结构只是定义接口的一种方法。但是,一旦定义它们,接口之间就没有真正的父子关系。例如:
interface Named {
name: string
}
interface Person extends Named {
age: number
}
interface Animal {
name: string
age: number
}
此处Person
和Animal
是同一类型。定义它们后,当其他代码使用它们时,编译器将以完全相同的方式对其进行处理:
function useNamed(named: Named) {
}
let p: Person = /* ... */
let a: Animal = /* ... */
useNamed(p) // OK
useNamed(a) // also OK, because if 'Animal' is compatible with
// `Named` then it is a `Named`
这就是为什么也可以使用交集类型创建相同类型的原因:
type Engine = Named & {
age: number
}
根据规范:
交叉点类型 表示同时具有多种类型的值。 A 和 B 的交集类型的值是 A 类型和类型的 both 的值> B 。 (来源:TypeScript Specification)
我们的Engine
类型既是Named
也是附加的定义:它在语义上与接口继承相同。这里的Engine
类型与Person
和Animal
完全相同。