TypeScript 5.0 Beta is available

TypeScript 5.0 Beta has been released and is available for download. You'll have to update your dependencies in your `package.json'.

  "devDependencies" : {
    ...
    "typescript" : "^5.0.0-beta"
    }

const Type Parameters

When you're inferring the object type, TypeScript will give you a general type.

type HasNames = { readonly names: string[] };

function getNamesExactly<T extends HasNames>(arg: T): T["names"] {
    return arg.names;
}

// Inferred type: string[]
const names = getNamesExactly({names: ["Alice", "Bob", "Eve"]});

but now you can add a const modifier to a type parameter declaration to cause const-like inference to be the default.

type HasNames = { names: readonly string[] };
function getNamesExactly<const T extends HasNames>(arg: T): T["names"] {
//                       ^^^^^
    return arg.names;
}

// Inferred type: readonly ["Alice", "Bob", "Eve"]
// Note: Didn't need to write 'as const' here
const names = getNamesExactly({ names: ["Alice", "Bob", "Eve"] });

Decorators

One of the most interesting additions for me is Decorators. These are an upcoming ECMAScript feature that allows the customisation of classes and members in a reusable way.

export class ProductService {
    public getProducts() {
        return fetch('/api/getProducts');
    };
}

If we wanted to trace this in development we could start adding in logger calls or the really dirty console.log() method. But with decorators we can create a decorator to wrap methods with the extra functionality.

function log(originalMethod: any, _context: any) {

    function replacementMethod(this: any, ...args: any[]) {
        console.log("LOG: Entering method.")
        const result = originalMethod.call(this, ...args);
        console.log("LOG: Exiting method.")
        return result;
    }

    return replacementMethod;
}
export class ProductService {
    @log
    public getProducts() {
        return fetch('/api/getProducts');
    };
}

So when we are now working in our project, we can flag a method with the decorator without added piles of extra code that you might want to remove later, or just making the code less readable. You can go further with this by extending the decorator further to match what you are trying to do.

Enums

Enums have been something that I find quite helpful in TypeScript. In TypeScript 5.0 there are now some improvements to how enums can be used. Previously you could pass thing in to an enum argument and TypeScript wouldn't raise an error. Now you will be a warning represented as you pass it in. However, I'd still use LogLevel.DEBUG instead of 0.

enum LogLevel {
    DEBUG,
    ERROR,
    WARNING,
}

const log = (level: LogLevel, message: string) => {
};

// Valid
log(2, "Error message");

log(LogLevel.WARNING, "Warning message");

// Invalid
log(1234, 'Invalid message')

Speed, Memory, and Package Size Optimisations

Taken straight from Microsoft's own blog, here are the improvements for installing and running TypeScript:

ScenarioTime or Size Relative to TS 4.9
material-ui build time90%
Playwright build time89%
tsc startup time89%
tsc build time86%
Outlook Web build time83%
VS Code build time81%
typescript Package Size58%

Microsoft are keeping quiet on how they made these improvements, but it's also mentioned that they've moved from namespaces to modules, probably inline with ESM plans. This would be extra useful with using Microsoft's Monaco package which had issues related to namespacing vs ESM.

Also, the TypeScript package is about 33% smaller now. This comes with some slim-lining some object types and adding uniformity.

This is all exciting to see, but it's still in Beta, so maybe roll back that beta dependency and wait on what Microsoft are going to hand out in the general release!

All articles are my own thoughts. Gathered from reading articles and trying things out.