TypeScript final class decorator

How to prevent a class from being inherited from in TypeScript.

TypeScript lacks the final class modifier common in other languages, but with the use of a decorator we can achieve similar functionality.

Final class decorator

export function final<T extends { new (...args: any[]): object }>(target: T): T {
    return class Final extends target {
        constructor(...args: any[]) {
            if (new.target !== Final) {
                throw new Error('Cannot inherit from final class');
            }
            super(...args);
        }
    };
}

Usage:

@final
export class Example {
}

An exception will be thrown if you try to inherit from Example and create a new instance of that class.

export class ExampleSub extends Example {
}

new ExampleSub(); // error is thrown

This exception will only happen at runtime, so keep that in mind.

Frozen class decorator

JavaScript also has the concept of freezing an object, which basically means that the object becomes immutable.

export function frozen(target: Function): void {
    Object.freeze(target);
    Object.freeze(target.prototype);
}

With this decorator you can prevent the class itself and its prototype from being changed.

Usage:

@frozen
export class Example {
}

const isFrozen = Object.isFrozen(Example); // true

Conclusion

You can combine these two together and prevent a class from being modified and inherited from.

You can find the source code in this gist.

Nuno Freitas
Posted by Nuno Freitas on October 28, 2017

Related articles