What Are Type Declaration Files In TypeScript?
Photo by Andreea Ch

What Are Type Declaration Files In TypeScript?


Subscribe to the newsletter

Get a once-per-week email with my latest content. By subscribing to this newsletter you will also be the first to receive last updates of my eBooks and courses.

0 members

You probably have seen files with a file extension like .d.ts in some JavaScript or TypeScript projects (libraries or frameworks) before and you wondered what are these files and what they are for. In TypeScript they are called Type Declaration files. Let’s find out what is that practically.

Let’s create a simple example with TypeScript code. Create a folder with the name typescript-type-defs or whatever name you want and then let’s create a file called users-list.ts there with code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
const users = [
  {
    id: "1",
    name: "John",
    username: "johnsmith11",
    age: 55,
    level: 23,
  },
  {
    id: "2",
    name: "C3PO",
    username: "iamnotrobot",
    age: 112,
    level: 1,
  },
];

export const NAME_FIELD_KEY: keyof User = "name";

interface User {
  id: string;
  name: string;
  username: string;
  age: number;
  level: number;
}

export function getEntityField<Entity>(
  entities: Entity[],
  fieldName: keyof Entity
): unknown[] {
  return entities.map((entity) => entity[fieldName]);
}

export function getUsersName(users: User[]): string[] {
  return getEntityField(users, NAME_FIELD_KEY) as string[];
}

const result = getUsersName(users);

console.log(result);

What if need to use Interface User somewhere else? Not a problem, just add export before interface:

1
2
3
4
5
6
7
export interface User {
  id: string;
  name: string;
  username: string;
  age: number;
  level: number;
}

You can import this interface from module users-list in another module. However, sometimes we need to use this interface as a common thing between several modules. So, exporting interface from one of these modules is not an option. We need to create a special file where we can specify Interface User and use it in modules.

Subscribe to the newsletter

Get a once-per-week email with my latest content. By subscribing to this newsletter you will also be the first to receive last updates of my eBooks and courses.

0 members

Create a file with name typings.d.ts and moved interface User from file users-list.ts into this new file:

1
2
3
4
5
6
7
export interface User {
  id: string;
  name: string;
  username: string;
  age: number;
  level: number;
}

Now we need to use this interface in module users-list. You can just import this interface from typings.d.ts:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import { User } from "./typings";

// ...

export const NAME_FIELD_KEY: keyof User = "name";

// ...

export function getUsersName(users: User[]): string[] {
  return getEntityField(users, NAME_FIELD_KEY) as string[];
}

// ...

Let’s look at file typings.d.ts more. In this file, you cannot write variables, functions, and other code of TypeScript/JavaScript. All you can write there is types or interfaces. You can only define types there and use them in any modules.

Usually, you don’t write types in .d.ts but in .ts files. However, .d.ts files are used in projects that are packages or libraries and are originally written in JavaScript. If you have JavaScript library and you have to add an ability to use your library in TypeScript projects, so you need to create .d.ts files. Another case is when you write your library in TypeScript but you ship it in compiled JavaScript code. In that case, you can automatically generate Type Declarations based on your TypeScript source code by using the TypeScript compiler (tsc).

Here is an example based on users-list.ts. Let’s use tsc to generate Type Declaration file:

1
tsc users-list.ts --declaration

After that you will see a new file called users-list.d.ts with the following code:

1
2
3
4
5
6
7
import { User } from "./typings";
export declare const NAME_FIELD_KEY: keyof User;
export declare function getEntityField<Entity>(
  entities: Entity[],
  fieldName: keyof Entity
): unknown[];
export declare function getUsersName(users: User[]): string[];

So with that Type Declaration file, you provide an ability to work with your library’s API and types to someone who uses your library in their project.

There is a huge repository that contains type definitions for many libraries and packages - DefinitelyTyped. You probably have installed npm packages with names like “@types/*”. The code of some of these packages is in this repository.

Subscribe to the newsletter

Get a once-per-week email with my latest content. By subscribing to this newsletter you will also be the first to receive last updates of my eBooks and courses.

0 members

Comments 💬