TypeScript .d.ts File
Learn what a .d.ts file (TypeScript declaration file) is and how .d.ts files relate to @types scoped packages. We will demonstrate .d.ts files using TypeScript with Express.
Table of Contents 📖
What is a .d.ts File?
A .d.ts file is a type declaration file for TypeScript, the d in .d.ts stands for declaration. These files don't contain any implementation information and aren't compiled to JavaScript like .ts files are. Instead, the TypeScript compiler uses these files to point out incorrect usage of code such as providing the wrong amount of arguments to a function or accessing a property on an object that doesn't exist.
Creating a .d.ts File
To demonstrate the usefullness of .d.ts files, lets work with Express in a TypeScript file. First, install express from npm by running npm i express.
npm i express
Now lets create a simple Express app and access a method, named wittCodeIsCool, that definitely does not exist with Express.
import express from 'express';
const app = express();
app.wittCodeIsCool() // Method wittCodeIsCool does not exist
What we would expect is for TypeScript to detect that the wittCodeIsCool method does not exist on the app object. However, this is not the case as we don't have any types information for Express that the TypeScript compiler can use. Therefore, TypeScript can't detect if the wittCodeIsCool method exists or not. To fix this, we can create our own types declaration file. Create a folder called @types and then place a file inside called express.d.ts. Note that the name of the file does not matter, besides the .d.ts of course, but its contents do.
mkdir @types
cd @types
touch express.d.ts
Inside this file, declare the module express and then provide type information for Express.
declare module 'express' {
export default function express(): ExpressApp;
interface ExpressApp {
wittCodeIsCool(): void;
}
}
Using declare module 'express' here tells TypeScript that we are defining types for the module express. Specifically we are saying that express exports a default function called express that returns an ExpressApp. An ExpressApp has a method called wittCodeIsCool that doesn't accept anything or return anything. Now, if we go back into index.ts and access a method from the app object called wittCodeIsNotCool we will get an error.
import express from 'express';
const app = express();
app.wittCodeIsCool();
app.wittcodeIsNotCool(); // Property 'wittcodeIsNotCool' does not exist on type 'ExpressApp'
Now the TypeScript compiler is reading information from our express.d.ts file so we get the useful errors that TypeScript provides. Of course, this is a custom types declaration file and does not actually provide the types Express provides. If we want to benefit from TypeScript when working with Express we need to install the npm package @types/express.
.d.ts Files and @types Scope
Whenever we install a package from npm with the @types scope, we are installing typing information provided in .d.ts files. For example, when we install Express with npm i express, we also want to install @types/express to get the typings Express has. To install Express typings as a development dependency, use the command npm i @types/express -D
npm i @types/express -D
Next, delete the @types folder that we created. Now TypeScript will be getting information from the @types/express npm library. Navigate back to index.ts and look at the information the TypeScript compiler is providing.
import express from 'express';
const app = express();
app.wittCodeIsCool(); // Property 'wittcodeIsCool' does not exist on type 'Express'
app.wittcodeIsNotCool(); // Property 'wittcodeIsNotCool' does not exist on type 'Express'
If we look for @types/express inside node_modules we can see that it contains an index.d.ts file.
[object Object]
This index.d.ts file contains all the typings information for Express and thus makes developing an Express application easier with TypeScript.