Daniel Rosenwasser, senior program manager for TypeScript, recently announced the beta release of TypeScript 5.4. TypeScript 5.4 features improved type inference, a new NoInfer
utility type, and breaking changes.
TypeScript 5.4 beta improved type inference for some types that are narrowed in closures.
function getUrls(url: string | URL, names: string[]) {
if (typeof url === "string") {
url = new URL(url);
}
return names.map(name => {
url.searchParams.set("name", name)
// ~~~~~~~~~~~~
// error!
// Property 'searchParams' does not exist on type 'string | URL'.
return url.toString();
});
}
In the code above, the url
variable inside the map
's arrow function’s closure is necessarily of type URL. Previous versions of TypeScript would infer url
's type as string | URL
as in the getUrls
function’s signature. The released beta correctly understands that the arrow function is always created after the last assignment to url
of an URL object and thus infers url
as having type URL
.
Some developers welcomed the improved inference on Twitter.
If those type narrowing changes are as good as they seem, that’s a huge improvement and will save a lot of unneeded if statements,
!
operators, and more. (Source)
Preserved Narrowing in Closures is going to be very helpful, thank you devs. (Source)
For more detail, developers can refer to the release note (Preserved Narrowing in Closures Following Last Assignments).
TypeScript 5.4 also adds declarations for JavaScript’s new Object.groupBy
and Map.groupBy
static methods. The release note warns:
Note also that these methods are only accessible by configuring your
target
toesnext
or adjusting yourlib
settings. We expect they will eventually be available under a stablees2024
target.
TypeScript additionally provide the new NoInfer
utility type for developers to opt out TypeScript’s type inference. NoInfer
allows developers to block inferences to valid but unwanted types. It is particularly useful when working with generic type parameters.
function createStreetLight<C extends string>(colors: C[], defaultColor?: NoInfer<C>) {
// ...
}
createStreetLight(["red", "yellow", "green"], "blue");
// ~~~~~~
// error!
// Argument of type '"blue"' is not assignable to parameter of type
// '"red" | "yellow" | "green" | undefined'.
In the previous code sample, TypeScript 5.4 assigns C as type of optional parameter defaultColor
but does not pursue its inference further, ultimately resolving C
type as "red" | "yellow" | "green"
. Previous versions of TypeScript (which do not have the NoInfer
utility type) infer the type of C
as "red" | "yellow" | "green" | "blue"
.
Developers can review the full release note on Microsoft’s developer blog, including the breaking changes resulting from the newly improved accuracy. The release note includes additional technical details, examples, and the full list of features part of the release.
Developers can install the released beta as follows:
npm install -D typescript@beta