TypeScript 5.4 Highlights: NoInfer, Object.groupBy and Smarter Narrowing
TypeScript 5.4 Highlights: NoInfer, Object.groupBy and Smarter Narrowing
TypeScript 5.4 is a small but very practical release. Here is what actually changes your day-to-day code.
1. NoInfer<T> utility type
You can now mark a generic type parameter as non-inferable, forcing TypeScript to use the explicit annotation:
function createStreetLight<C extends string>(
colors: C[],
defaultColor?: NoInfer<C>
) { /* ... */ }
createStreetLight(["red", "yellow", "green"], "red"); // ✅
createStreetLight(["red", "yellow", "green"], "blue"); // ❌ error
Without NoInfer, the compiler would widen C to include "blue". This was a frequent source of subtle bugs in API design.
2. Preserved narrowing in closures after last assignment
Before 5.4, narrowing was lost inside callbacks:
function f(x: string | number) {
if (typeof x === "string") {
return () => x.toUpperCase(); // x was widened to string | number
}
}
Now the compiler tracks that x was last assigned a string and keeps the narrowing inside the closure.
3. Object.groupBy and Map.groupBy
ECMAScript 2024 added Object.groupBy, and TypeScript 5.4 ships the types:
const items = [{ kind: "fruit" }, { kind: "veg" }, { kind: "fruit" }];
const grouped = Object.groupBy(items, (i) => i.kind);
// { fruit: [...], veg: [...] }
4. Take-aways
- Use
NoInferwhenever a generic appears in two argument positions and only one should drive inference. - Trust the compiler more inside callbacks — fewer
ascasts. - Replace lodash
groupBywith the standard library where you can.
Found this helpful? Try our free tools!
Explore Our Tools →