TypeScript release

TypeScript 4.2 for JavaScript users

  • Released 23 February 2021
  • Examples run with TypeScript 5.9

TypeScript 4.2 was announced on 23 February 2021. One of its breaking changes is about JavaScript files only: f<T>(100) in a .js file is now parsed the way JavaScript parses it, as two comparisons, (f < T) > 100. Type arguments were never allowed in JavaScript; now they are not even read as such.

The release also added --explainFiles, which says why each file is part of the program, and new checks that apply to .js files: an implicit any from a yield expression, and a function tested in a condition instead of called.

At a glance

ReleaseTypeScript 4.2
Released23 February 2021, the day of its announcement on the TypeScript blog
SourceTypeScript 4.2 release notes
ExamplesEvery example runs through TypeScript 5.9.3 when this site is built.
Previous releaseTypeScript 4.1
Next releaseTypeScript 4.3

What changed for JavaScript

Type arguments in .js files are comparisons

JavaScript has no syntax for explicit type arguments, and since 4.2 TypeScript does not parse first<string>(x) as a call with one: it is first < string > x, which then fails as a comparison (TS2365, TS2693). Let inference choose the type, or give the argument a type with a JSDoc cast.

list.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: list.js(13,13): error TS2365: Operator '>' cannot be applied to types 'boolean' and 'unknown[]'. list.js(13,19): error TS2693: 'string' only refers to a type, but is being used as a value here. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. list.js(13,13): error TS2365: Operator '>' cannot be applied to types 'boolean' and 'unknown[]'. list.js(13,19): error TS2693: 'string' only refers to a type, but is being used as a value here. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. list.js(13,13): error TS2365: Operator '>' cannot be applied to types 'boolean' and 'unknown[]'. list.js(13,19): error TS2693: 'string' only refers to a type, but is being used as a value here. checked 21 October 2026
/**
 * @template T
 * @param {T[]} items
 * @returns {T | undefined}
 */
export function first(items) {
  return items[0];
}

/** @type {unknown[]} */
const rows = ["TEE-01"];
const sku = first<string>(rows);error TS2365: Operator '>' cannot be applied to types 'boolean' and 'unknown[]'.error TS2693: 'string' only refers to a type, but is being used as a value here.

export { sku };
JavaScript has no syntax for explicit type arguments.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

Implicit any from yield

Under noImplicitAny, keeping the result of a yield is now an error (TS7057) when nothing tells TypeScript its type. Give the generator a type with @returns {Generator<Yielded, Returned, Received>}.

prompts.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: prompts.js(3,16): error TS7057: 'yield' expression implicitly results in an 'any' type because its containing generator lacks a return-type annotation. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. prompts.js(3,16): error TS7057: 'yield' expression implicitly results in an 'any' type because its containing generator lacks a return-type annotation. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. prompts.js(3,16): error TS7057: 'yield' expression implicitly results in an 'any' type because its containing generator lacks a return-type annotation. checked 21 October 2026
export function* askLoose() {
  const name = yield "Name?";error TS7057: 'yield' expression implicitly results in an 'any' type because its containing generator lacks a return-type annotation.
  return name;
}

/** @returns {Generator<string, string, string>} */
export function* ask() {
  const name = yield "Name?";
  return name.trim();
}
The value a yield receives is an implicit any without a Generator type.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": [
    "*.js"
  ]
}

Functions tested instead of called

Under strictNullChecks, a function used as a condition inside && or || is reported when it is always defined: isEnabled && item.visible is almost always a missing () (TS2774).

filter.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: filter.js(7,33): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. filter.js(7,33): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. filter.js(7,33): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? checked 21 October 2026
/**
 * @param {{ visible: boolean }[]} items
 * @param {() => boolean} isEnabled
 */
export function shown(items, isEnabled) {
  return items.filter((item) => isEnabled && item.visible);error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
A function used as a condition inside && is reported.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": [
    "*.js"
  ]
}

--explainFiles

Run tsc -p jsconfig.json --explainFiles to print every file in the program and the reason it is there: matched by include, imported by another file, or a lib or @types package. It is the quickest way to find out why a file outside your source folder is checked.

Terminal
npx tsc -p jsconfig.json --explainFiles

noPropertyAccessFromIndexSignature

A new option, outside strict, requires bracket access for keys that only an index signature declares, so a typo in a dotted property name cannot pass as a lookup.

main.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: main.js(11,22): error TS4111: Property 'locale' comes from an index signature, so it must be accessed with ['locale']. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. main.js(11,22): error TS4111: Property 'locale' comes from an index signature, so it must be accessed with ['locale']. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. main.js(11,22): error TS4111: Property 'locale' comes from an index signature, so it must be accessed with ['locale']. checked 21 October 2026
/**
 * @typedef {object} Settings
 * @property {string} theme
 */

/** @type {Settings & Record<string, string>} */
const settings = { theme: "dark", locale: "en-US" };

console.log(settings.theme);
console.log(settings.locale);error TS4111: Property 'locale' comes from an index signature, so it must be accessed with ['locale'].
console.log(settings["locale"]);
noPropertyAccessFromIndexSignature on: dot access to an index-signature key.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": [],
    "noPropertyAccessFromIndexSignature": true
  },
  "include": [
    "*.js"
  ]
}

What did not change

TypeScript still does not accept type arguments in JavaScript; the change is in how the text is parsed, which matters most to tools that read JavaScript through TypeScript's parser.

Upgrade notes

From the breaking changes:

  • New TS7057 errors for generators under noImplicitAny.
  • Uncalled-function checks in && and || under strictNullChecks.
  • An import path ending in .d.ts is an error; import the module path instead.
  • The in operator's right side must be an object.

Gotchas

  • An underscore prefix (_first) now marks a destructured name as intentionally unused for noUnusedLocals.

Sources

Last reviewed 20 October 2026.