The short answer
Check npm for @types/<name> first. If there is none, write a declaration file in your project with declare module "<name>", describe the exports you use, and include the file in jsconfig.json:
declare module "tiny-csv" {
export interface ParseOptions {
/** The field separator; "," when left out. */
delimiter?: string;
}
export function parse(text: string, options?: ParseOptions): string[][];
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": [],
"maxNodeModuleJsDepth": 0
},
"include": ["*.js", "types/*.d.ts"]
} The JavaScript that imports the package is then checked against those declarations:
import { parse } from "tiny-csv";
const rows = parse("sku;quantity\nLAMP-01;4", { delimiter: ";" });
for (const [sku, quantity] of rows) {
console.log(sku.toLowerCase(), Number(quantity));
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": [],
"maxNodeModuleJsDepth": 0
},
"include": ["*.js", "types/*.d.ts"]
} Why it works
declare module "tiny-csv" { … } tells tsc what the module named tiny-csv exports, wherever the import is. Declaration files hold types only, so the syntax inside is TypeScript’s (export function parse(…): string[][];), even in a JavaScript project. tsc finds the file because include lists types/*.d.ts; it does not have to sit next to the package.
The same thing in TypeScript
A TypeScript project uses the same .d.ts file in the same way; declaration files are the one place where JavaScript and TypeScript projects write identical code. That is why this example has no TypeScript tab.
What goes wrong
Without a declaration, and with maxNodeModuleJsDepth at 0, the import is TS7016 and the package is any:
import { parse } from "tiny-csv";error TS7016: Could not find a declaration file for module 'tiny-csv'. '/project/node_modules/tiny-csv/index.js' implicitly has an 'any' type.
Try `npm i --save-dev @types/tiny-csv` if it exists or add a new declaration (.d.ts) file containing `declare module 'tiny-csv';`
console.log(parse("sku,quantity"));jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": [],
"maxNodeModuleJsDepth": 0
},
"include": ["*.js"]
} With the declaration, calls are checked: an option the declaration does not list fails (TS2353):
import { parse } from "tiny-csv";
parse("sku;quantity", { separator: ";" });error TS2353: Object literal may only specify known properties, and 'separator' does not exist in type 'ParseOptions'.jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": [],
"maxNodeModuleJsDepth": 0
},
"include": ["*.js", "types/*.d.ts"]
} Gotchas
declare module "tiny-csv";alone silences TS7016. That one-line form, which tsc’s own message suggests, types the whole module asany; use it only as a stopgap.- The
.d.tsmust not have top-level imports or exports. A top-levelimportturns the file into a module, and itsdeclare modulebecomes an augmentation of an existing module instead of a new declaration: the import is TS7016 again. skipLibCheckskips your file too. WithskipLibCheckon (thejsconfig.jsondefault), a typo inside the.d.tsitself goes unreported; the calls against it are still checked.
Questions
Why do I not get TS7016 in my project?
A jsconfig.json sets maxNodeModuleJsDepth to 2, so tsc reads the package's JavaScript and infers what it can instead of reporting TS7016. The inferred types are often loose (parameters become any); a declaration file replaces them. The examples here set the option to 0, the tsconfig.json default, to show the plain case.
Should I publish my declarations?
If they are good, consider sending them to DefinitelyTyped as @types/<name>, or to the package itself. Until then, a file in your repository works the same way.
Sources
- Modules .d.ts (declaration file templates) · TypeScript handbook
- Declaration files (consumption) · TypeScript handbook
- DefinitelyTyped · GitHub
Last reviewed 21 October 2026.