Types in TypeScript
In TypeScript, the type
keyword is used to define complex types that can't be described with a single type keyword. The type
keyword provides an alias for a more complex type declaration, allowing for more concise and readable code.
Here's an example of how you might use a type
in TypeScript:
type Point = {
x: number;
y: number;
};
In this example, we define a type Point
that represents a coordinate on a two-dimensional plane.
Interfaces in TypeScript
An interface
in TypeScript is a way of defining a contract for a certain structure of an object. Interfaces are primarily used for defining object structures and for class-to-class inheritance.
Here's an example of how you might use an interface
in TypeScript:
interface Point {
x: number;
y: number;
}
Similar to the type example, we define an interface Point
that represents a coordinate on a two-dimensional plane.
Differences between Types and Interfaces
Both type
and interface
are fundamental constructs that allow you to define new types in your program, but they work in subtly different ways and are suited to different types of problems.
Declaration Merging
One key difference is that interface
can be merged, but types cannot. In TypeScript, if you declare an interface
multiple times, the declarations will be combined into a single interface
.
interface Foo {
x: number;
}
interface Foo {
y: number;
}
// Foo is now { x: number; y: number; }
With type
, however, the same operation would result in a duplicate identifier error:
type Bar = {
x: number;
};
type Bar = {
y: number;
};
// Error: Duplicate identifier 'Bar'.
Extending and Implementing
interface
can extend and be extended by other interface
, and they can also be implemented by classes. This can provide a form of code contract in the class implementation.
interface A {
x: number;
}
interface B extends A {
y: number;
}
class MyClass implements B {
x = 5;
y = 10;
}
type
, on the other hand, can extend and intersect other type
, but cannot be implemented by classes:
type C = {
x: number;
};
type D = C & {
y: number;
};
// This won't work
class MyOtherClass implements D {
x = 5;
y = 10;
}
// Error: Class 'MyOtherClass' incorrectly implements interface 'D'.
// Property 'x' is missing in type 'MyOtherClass' but required in type 'D'.
Use with Primitive Types
The type
keyword can represent primitive types such as string
, number
, boolean
, null
, undefined
, etc. In contrast, interface
are only meant to represent the shape of object types.
type MyString = string;
type NullableNumber = number | null;
Computed Properties
typ
aliases can have computed properties, while interface
can not:
type ComputedType = {
[P in 'x' | 'y']: number;
};
// This is invalid for interfaces
interface ComputedInterface {
[P in 'x' | 'y']: number;
}
// Error: An index signature parameter type cannot be a union type. Consider using a mapped object type instead.
Literal Types
type
aliases can express literal types, and they can combine them in ways that can't be done with interface
.
type Direction = 'North' | 'East' | 'South' | 'West';