All Articles

Everything you need to know about TypeScript 5.1 beta

Matt Pocock
Matt PocockMatt is a well-regarded TypeScript expert known for his ability to demystify complex TypeScript concepts.

The TypeScript 5.1 beta is out - here's everything you need to know:

It's only a small release

5.1 doesn't bring much in the way of new features. It's not got much in the way of new keywords or new tools for transforming types.

One small improvement is to usability improvements in functions which return ,undefined. If you've got a type that expects () => undefined...

type FunctionReturningUndefined = () => undefined 

...in 5.0 you'd need to explicitly return a value of undefined for it to work:

// Type '() => void' is not assignable to type
// 'FunctionReturningUndefined'.
const myFunc: FunctionReturningUndefined = () => {}

const myFunc2: FunctionReturningUndefined = () => {
  // Now it's happy!
  return undefined
}

But in 5.1, both of the above cases will pass.

Another nice feature is linked cursors in JSX. This means when you're editing the opening tag of a <div> in JSX, it'll also edit the closing tag. Beautiful.

These are nice usability improvements, but even together they don't feel like enough for a new TS version. So - what's the headline?

5.1 unblocks React Server Components

This is why 5.1 is shipping now. React Server Components don't really work in TypeScript.

The reason for that is that React Server Components introduced async components:

tsx
const MyAsyncComponent = async () => {
return <div></div>
}
const Parent = () => {
// 'MyAsyncComponent' cannot be used as a JSX
// component. Its return type 'Promise<Element>'
// is not a valid JSX element.
return <MyAsyncComponent />
}

Before 5.1, TypeScript hard-coded an idea of what they expected valid JSX elements to be - it was JSX.Element | null. Along with blocking Server Components, this meant that perfectly valid React code, like returning strings from components, was not allowed:

tsx
const MyStringComponent = () => {
return 'Hello world!'
}
const Parent = () => {
// 'MyStringComponent' cannot be used as a JSX component.
// Its return type 'string' is not a valid JSX element.
return <MyStringComponent />
}

Now, TypeScript will consult a global type called JSX.ElementType to calculate if a JSX component is valid. This gives frameworks that use JSX (like React, Solid and Qwik) a LOT more control over what constitutes a valid JSX element - opening up the potential for new API's using JSX itself.

Should I upgrade?

I've tested 5.1 with Total TypeScript so far, and I've seen no breaking changes. I imagine you're safe to upgrade - and if you're using React Server Components, it's an absolute must.

If you've enjoyed this breakdown, check out my video on Total TypeScript to learn more.

Matt's signature

Share this article with your friends

`any` Considered Harmful, Except For These Cases

Discover when it's appropriate to use TypeScript's any type despite its risks. Learn about legitimate cases where any is necessary.

Matt Pocock
Matt Pocock

No, TypeScript Types Don't Exist At Runtime

Learn why TypeScript's types don't exist at runtime. Discover how TypeScript compiles down to JavaScript and how it differs from other strongly-typed languages.

Matt Pocock
Matt Pocock

Deriving vs Decoupling: When NOT To Be A TypeScript Wizard

In this book teaser, we discuss deriving vs decoupling your types: when building relationships between your types or segregating them makes sense.

Matt Pocock
Matt Pocock

NoInfer: TypeScript 5.4's New Utility Type

Learn how TypeScript's new utility type, NoInfer, can improve inference behavior by controlling where types are inferred in generic functions.

Matt Pocock
Matt Pocock