M Logo
๐Ÿ“ TypeScript from Zero ยท Part 45 of 50

TypeScript Declaration Files: .d.ts, declare module and @types Packages (TS7016)

November 6, 2026

Welcome to episode 45 of TypeScript from Zero, a series for complete beginners (no JavaScript needed). Welcome back to TypeScript from zero! Not all code is TypeScript. There is a lot of plain JavaScript in the world, and we want to use it with types. The tool for that is the declaration file: a file with only types, and no code. Today we make some, and we meet at types packages. We start with a plain JavaScript file, legacy.js. Every code block below is the exact code and output from the video, ready to copy.

Setup

We start in the terminal and open the project in VS Code:

bash
cd tasks
touch src/legacy.js
code .

1. JavaScript

This is JavaScript: a function without any types. Slugify turns a title into a piece of a web address. In a second file, a TypeScript file, we import it and use it. Node runs this without problems: hello dash type dash script.

src/legacy.js:

ts
export function slugify(text) {
  return text.toLowerCase().trim().split(" ").join("-");
}

src/use-legacy.ts:

ts
import { slugify } from "./legacy.js";
console.log(slugify("Hello Type Script"));
text
$ node src/use-legacy.ts
hello-type-script

2. TS7016

But tsc says: could not find a declaration file for module legacy.js, and the file implicitly has an any type. TS70016. Our strict settings do not accept a module that is not described.

text
$ npx tsc --noEmit
src/use-legacy.ts:1:25 - error TS7016: Could not find a declaration file for module './legacy.js'. '/home/mah/tasks/src/legacy.js' implicitly has an 'any' type.

1 import { slugify } from "./legacy.js";
                          ~~~~~~~~~~~~~

Found 1 error in src/use-legacy.ts:1

3. d.ts

We describe it. A file with the same name, but ending in.d.ts: legacy.d.ts. It holds only declarations, without bodies. Slugify takes a string, and returns a string. tsc is happy now. And the description works: if we call slugify with a number, tsc stops us, though the JavaScript underneath knows nothing about types.

src/legacy.d.ts:

ts
export function slugify(text: string): string;
bash
$ npx tsc --noEmit

4. Fix

We delete the wrong call.

bash
$ npx tsc --noEmit

5. declare module

Packages from npm can be untyped too. We install is odd, a tiny package, and use it. It runs, and it prints true. But tsc complains again with TS70016, and this time it even gives us two tips. One of them is the way for us: declare module, with the name of the package, and a block of declarations. We put it in a.d.ts file.

text
$ npm install is-odd

added 2 packages, and audited 8 packages in 464ms

1 package is looking for funding
  run `npm fund` for details

found 0 vulnerabilities

src/use-odd.ts:

ts
import isOdd from "is-odd";
console.log(isOdd(3));
text
$ node src/use-odd.ts
true
text
$ npx tsc --noEmit
src/use-odd.ts:1:19 - error TS7016: Could not find a declaration file for module 'is-odd'. '/home/mah/tasks/node_modules/is-odd/index.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/is-odd` if it exists or add a new declaration (.d.ts) file containing `declare module 'is-odd';`

1 import isOdd from "is-odd";
                    ~~~~~~~~

Found 1 error in src/use-odd.ts:1

6. @types

For popular packages, other people have already written the declarations, and published them as types packages. Lodash is an example. We install it, and use the chunk function. It works, but tsc asks for the declarations again. The tip is exact: npm install, -- save dash dev, at types slash lodash. After that, tsc knows every function of lodash, with its types.

text
$ npm install lodash

added 1 package, and audited 9 packages in 487ms

1 package is looking for funding
  run `npm fund` for details

found 0 vulnerabilities

src/use-lodash.ts:

ts
import _ from "lodash";
console.log(_.chunk([1, 2, 3, 4], 2));
text
$ node src/use-lodash.ts
[ [ 1, 2 ], [ 3, 4 ] ]
text
$ npx tsc --noEmit
src/use-lodash.ts:1:15 - error TS7016: Could not find a declaration file for module 'lodash'. '/home/mah/tasks/node_modules/lodash/lodash.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/lodash` if it exists or add a new declaration (.d.ts) file containing `declare module 'lodash';`

1 import _ from "lodash";
                ~~~~~~~~

Found 1 error in src/use-lodash.ts:1
text
$ npm install --save-dev @types/lodash

added 1 package, and audited 10 packages in 472ms

1 package is looking for funding
  run `npm fund` for details

found 0 vulnerabilities

Recap

Today: a declaration file next to a JavaScript file, declare module for an untyped package, and at types packages from the community. Next episode: branded types.

ยฉ 2026 All Rights Reserved By Mahmudul Alam