Paul Krill
Editor at Large

TypeScript soothes type narrowing pain point

news
Mar 07, 20243 mins
JavaScriptProgramming LanguagesSoftware Development

TypeScript 5.4, now generally available, preserves type refinements in function closures following last assignments.

A pile of wooden letters.
Credit: Shaldark Illustrations/Shutterstock

TypeScript 5.4, a planned update to the strongly typed JavaScript variant from Microsoft, is now generally available. New capabilities in version 5.4 include preserved narrowing within function closures created after the last assignment and a NoInfer type to block inferences to valid but unwanted types.

The general release was published on March 6. The release candidate was published February 22, following a beta release from January 29. TypeScript 5.4 can be accessed via NuGet or NPM. In NPM, use the following command:

npm install -D typescript@

Prior to the final release, release notes were updated to document notable behavioral changes including restrictions around enum capabilities, improvements in mapped type behavior, and restrictions on enum member naming. The final release also documents new auto-import support for subpath imports. Previously, TypeScript’s auto-imports did not consider paths in imports that could be “frustrating,” requiring users to manually define paths in their tsconfig.json.  

Detailing the type narrowing improvement, Microsoft said a common pain point in TypeScript was that narrowed types were not always preserved within function closures. In TypeScript 5.4, when parameters and let variables are used in non-hoisted functions, the type checker will look for a last assignment point. If one is found, TypeScript can narrow from outside the containing function.

TypeScript 5.4 also introduces a NoInfer<T> utility type. Surrounding a type in NoInfer<…> gives a signal to TypeScript to match the inner types to find candidates for type inference. The utility type addresses an issue in which TypeScript can infer type arguments from whatever is passed in. But it is not always clear what is the best type to infer, leading TypeScript to reject valid calls and make other mistakes.

Other improvements in TypeScript 5.4:

  • TypeScript more accurately checks whether or not strings are assignable to the placeholder slots of a template string type.
  • New assignability restrictions have been introduced for enums. Previously, when two enums had the same names and the same enum member names, they were considered compatible, but TypeScript would silently allow them to have differing values. TypeScript 5.4 requires the values to be identical (when known). There also are new restrictions for when one of the enum members does not have a statically known value. And TypeScript no longer allows enums to use the names Infinity, -Infinity, or NaN.
  • Declarations are added for JavaScript’s new groupBy and Map.groupBy static methods. Object.groupBy takes an iterable and a function deciding which group each element should be placed in. The function must make a key for each distinct group, and Object.groupBy uses that key to make an object where every key maps to an array containing the original element. Map.groupBy is similar, but produces a Map rather than a plain object.
  • Support has been added for require( ) calls in --moduleResolution bundler and --module preserve.
  • Import attributes and assertions are now checked against the global ImportAttributes type. This means runtimes now can more accurately describe the import attributes.
  • A Quick Fix allows you to add a new parameter to functions called with too many arguments.
  • TypeScript now reduces intersections with type variables and primitives more aggressively, depending on how the type variable’s constraint overlaps with these primitives.
  • Deprecations have been added from TypeScript 5.0 such as target: ES3 code, NoImplcitUseStrict, charset, and out. TypeScript 5.4 likely will be the last version in which the list of deprecations continues to function as normal.

TypeScript 5.4 follows predecessor TypeScript 5.3, released in November 2023 and featuring import attributes for ECMAScript modules.