TypeScript 4.6 was announced on 28 February 2022. It changed something for every JavaScript file an editor opens, checked or not: TypeScript now reports JavaScript syntax and binding errors, such as a const declared twice, in .js files without checkJs or // @ts-check.
For checked files the release adds narrowing that plain JavaScript benefits from: destructured parts of a discriminated union stay linked, and parameters typed by a union of tuples narrow each other.
At a glance
| Release | TypeScript 4.6 |
|---|---|
| Released | 28 February 2022, the day of its announcement on the TypeScript blog |
| Source | TypeScript 4.6 release notes |
| Examples | Every example runs through TypeScript 5.9.3 when this site is built. |
| Previous release | TypeScript 4.5 |
| Next release | TypeScript 4.7 |
What changed for JavaScript
Syntax and binding errors in every JavaScript file
Before 4.6, an unchecked .js file got almost no errors. Now TypeScript reports JavaScript's own syntax and binding errors there too: a block-scoped name declared twice (TS2451), a modifier where JavaScript does not allow one, and the like. They show up in editors that use TypeScript's language service and when tsc reads a JavaScript file. Type errors still need checkJs.
The release notes give one way to silence them in a file: // @ts-nocheck at the top. This site's tests add a second with TypeScript 5.9: the errors appear only when checkJs is left out of the config. An unchecked file with a duplicate const gets TS2451 then, and nothing with "checkJs": false or with // @ts-nocheck.
Destructured discriminated unions
When kind and payload are destructured from a discriminated union into const bindings (or parameters that are never reassigned), checking kind now narrows payload too.
/**
* @typedef {{ kind: "count", payload: number } | { kind: "label", payload: string }} Action
*/
/** @param {Action} action */
export function describe(action) {
const { kind, payload } = action;
if (kind === "count") {
return payload.toFixed(0);
}
return payload.toUpperCase();
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": [
"*.js"
]
} Parameters that depend on each other
A function typed with a rest parameter that is a union of tuples, (...args: ["count", number] | ["label", string]) => string, narrows its second parameter when you check the first. In JavaScript, put the function type in a @type tag on the variable that holds the function.
/** @type {(...args: ["count", number] | ["label", string]) => string} */
export const format = (kind, value) => {
if (kind === "count") {
return value.toFixed(0);
}
return value.toUpperCase();
};
format("count", 3);
format("label", "sale");jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": [
"*.js"
]
} Mismatched @param names in TypeScript files
In a checked .js file a @param name that matches no parameter was already an error (TS8024). 4.6 adds an editor suggestion for the same mistake in .ts files, where JSDoc carries no types.
/** @param {number} qty */error TS8024: JSDoc '@param' tag has name 'qty', but there is no parameter with that name.
export function double(quantity) {error TS7006: Parameter 'quantity' implicitly has an 'any' type.
return quantity * 2;
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} target es2022
The es2022 target and lib bring Array.prototype.at(), Object.hasOwn and the cause option of Error.
Code before super()
A subclass with field initializers may now run code before super() in its constructor, as long as that code does not touch this; before 4.6 any code there was an error.
What did not change
Type checking in .js files is still opt-in: without checkJs or // @ts-check, the new errors are JavaScript errors, not type errors.
Upgrade notes
Two breaking changes in the release notes:
- Unchecked JavaScript files now show syntax and binding errors; add
// @ts-nocheckto a file you do not want TypeScript to report anything in, or set"checkJs": falsefor the whole project. - An object rest on a generic value now drops methods and other members a spread would not copy.
Gotchas
// @ts-nocheckturns off everything TypeScript reports in that file, the new JavaScript errors included, so use it on files you cannot change rather than to hide one error.
Sources
- TypeScript 4.6 release notes · TypeScript handbook
- Announcing TypeScript 4.6 · TypeScript blog
Last reviewed 20 October 2026.