ยท new features

What is Type Compatibility in TypeScript?

TypeScript has a structural type system, which means that types are compatible based on their shape or structure rather than their names. This allows you to interchangeably use types with different names but identical properties. You can assign one type to another if they share the same properties, including optional properties.

TypeScript uses a structural type system, which means that type compatibility is based on the shape or structure of the types rather than their explicit declarations or names. This allows you to define two types with different names but identical properties, enabling interchangeability between them.

Contents

Assignment Compatibility

One type can be assigned to another if they share at least the same properties. The assigned type must include all the required properties of the target type, with compatible types for each property.

In the example below, an instance of Dog can be passed to the logCatName function since both Cat and Dog types have the same properties:

type Cat = {
  age: number;
  name: string;
}
 
type Dog = {
  age: number;
  name: string;
}
 
function logCatName(animal: Cat) {
  console.log(animal.name);
}
 
const bobby: Dog = {
  age: 5,
  name: 'Bobby'
};
 
logCatName(bobby);

Optional and Additional Properties

The compatibility remains intact even when optional properties (e.g., catTag) don't conflict in terms of typing. Additional properties, such as dogTag, are compatible as long as the target type doesn't explicitly prohibit them:

type Cat = {
  age: number;
  name: string;
  catTag?: number;
}
 
type Dog = {
  age: number;
  name: string;
  dogTag: number;
}
 
function logCatName(animal: Cat) {
  console.log(animal.name);
}
 
const bobby: Dog = {
  age: 5,
  name: 'Bobby',
  dogTag: 1337
};
 
logCatName(bobby);

Disallowing Properties

To explicitly disallow a property, you can utilize the never type, which will require you to update your code:

type Cat = {
  age: number;
  name: string;
  catTag?: number;
  dogTag: never;
}
 
type Dog = {
  age: number;
  name: string;
  dogTag: number;
}
 
function logCatName(animal: Cat) {
  console.log(animal.name);
}
 
const bobby: Dog = {
  age: 5,
  name: 'Bobby',
  dogTag: 1337
};
 
// TS2345: Argument of type 'Dog' is not assignable to parameter of type 'Cat'.
logCatName(bobby);

Preventing Compatibility

Type compatibility applies not only to plain types but also to instances of classes. If you want to prevent type compatibility, you can use Discriminated Unions or the branded types programming pattern.

Back to Blog