There are technical differences between interface
and type
that are well-described here.
However, for the cases where a type
and an interface
can both be used, there is no semantic difference at all.
About interface
inheritance and type
intersection in TypeScript
In TypeScript, the hierarchy between interfaces is just a way to define interfaces. But once they are defined, there is no real parent-child relationships between interfaces. For example:
interface Named {
name: string
}
interface Person extends Named {
age: number
}
interface Animal {
name: string
age: number
}
Here Person
and Animal
are the same type. Once they are defined, they will be processed exactly the same way by the compiler when other code use them:
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`
That's why the same type can also be created using an intersection type:
type Engine = Named & {
age: number
}
From the specification:
Intersection types represent values that simultaneously have multiple types. A value of an intersection type A & B is a value that is both of type A and type B. (source: TypeScript Specification)
Our Engine
type is both a Named
and the additional definition: it is semantically the same thing as interface inheritance. And Engine
type here is exactly the same type as Person
and Animal
.