Decorador para classe final em TypeScript

Como impedir uma classe de ser herdada em TypeScript.

O TypeScript não tem um modificador de classe final como outras linguagens, mas com o uso de um decorador podemos atingir uma funcionalidade semelhante.

Decorador de classe final

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);
        }
    };
}

Uso:

@final
export class Example {
}

Uma excepção será lançada se tentarem herdar de Example e criar uma nova instância dessa classe.

export class ExampleSub extends Example {
}

new ExampleSub(); // error is thrown

Tenham em mente que esta excepção só acontece em runtime.

Decorador de classe congelada

O JavaScript tem o conceito de congelar um objecto, que significa basicamente que o objecto se torna imutável.

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

Com este decorador impedimos que a própria classe e o seu protótipo sejam modificados.

Uso:

@frozen
export class Example {
}

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

Conclusão

Podemos combinar ambos os decoradors e impedir uma classe de ser modificada e herdada.

Podem encontrar o código fonte neste gist.

Artigos relacionados