This chapter gives an overview of strategies for migrating code bases from JavaScript to TypeScript. It also mentions material for further reading.
The TypeScript compiler supports a mix of JavaScript and TypeScript files if we use the compiler option --allowJs
:
At first, there are only JavaScript files. Then, one by one, we switch files to TypeScript. While we do so, our code base keeps being compiled.
This is what tsconfig.json
looks like:
{
"compilerOptions": {
···
"allowJs": true
}
}
More information:
This approach works as follows:
--noEmit
). In addition to the compiler option --allowJs
(for allowing and copying JavaScript files), we also have to use the compiler option --checkJs
(for type-checking JavaScript files).
.js
files to .ts
files is not urgent now because the whole code base is already fully statically typed. We can even produce type files (filename extension .d.ts
) now.
This is how we specify static types for plain JavaScript via JSDoc comments:
/**
* @param {number} x - The first operand
* @param {number} y - The second operand
* @returns {number} The sum of both operands
*/
function add(x, y) {
return x + y;
}
/** @typedef {{ prop1: string, prop2: string, prop3?: number }} SpecialType */
/** @typedef {(data: string, index?: number) => boolean} Predicate */
More information:
Projects that migrate to TypeScript often start with the default type checking and then add more checks, in stages – e.g.:
strictNullChecks
(prevents undefined
and null
from being used unless the type is T | undefined
or T | null
, respectively)
noImplicitAny
(prevents omitting types for parameters and more)
strict
(includes the previous two compiler options – which can be removed – and adds additional ones)
In contrast to compiler options, we can activate linting options on a per-file basis. This helps when switching from less strict type checking to stricter type checking: We can lint before making the switch. These are examples of useful rules that the TypeScript linter typescript-eslint provides:
noImplicitAny
:
erasableSyntaxOnly
:
In large JavaScript projects, switching to TypeScript may produce too many errors – no matter which approach we choose. Then snapshot-testing the TypeScript errors may be an option:
More information:
ts-migrate helps with the first step of moving from JavaScript to TypeScript: “The resulting code will pass the build, but a followup is required to improve type safety. There will be lots of //@ts-expect-error
, and any
that will need to be fixed over time. In general, it is a lot nicer than starting from scratch.”
type-coverage shows which percentage of identifiers have the type any
.
We have taken a quick look at strategies for migrating to TypeScript. Two more tips:
Further reading: