DEV Community

Cover image for Existe imutabilidade no JS/TS? Como funciona?
Fernando Gustavo
Fernando Gustavo

Posted on

Existe imutabilidade no JS/TS? Como funciona?

E aí, galera!

Resumindo e dando a resposta, que é um pouco contraintuitiva para quem vem de outras linguagens, não, não existe imutabilidade garantida no tempo de execução do JavaScript ou TypeScript. Mas o TypeScript nos oferece alguns caminhos para forçar essa prática e te avisar dos erros antes que teu código rode.

TL;DR:
Mas é algo interessante.

Vou te mostrar o motivo por trás disso e como usar o TypeScript para escrever um código muito mais seguro e fácil de entender.

A raiz do problema: JavaScript é mutável por natureza

O JavaScript foi construído com a ideia de mutabilidade para a maioria dos seus tipos de referência, como por exemplo, objetos e arrays.

Quando usamos const, a única coisa que garantimos é que a variável não será reatribuída. O conteúdo do objeto ou array que ela aponta na memória pode ser alterado livremente:

const user = { name: "Fernando", languages: 5 };

// O objeto interno foi alterado, e o TS não reclama.
user.languages = 4;
Enter fullscreen mode Exit fullscreen mode

Em projetos grandes, se você passa esse objeto para várias funções (em um componente React, por exemplo), qualquer função pode mudar ele sem aviso, gerando um side effect por exemplo. A imutabilidade é a prática de sempre criar uma nova cópia ao invés de alterar o original, mas o JavaScript não te obriga a isso.

A solução: TypeScript

O TypeScript atua como um sistema de tipos rodando em tempo de compilação. Ele usa isso para nos dar opções que obrigam a imutabilidade como uma regra, não como um recurso da linguagem.


O uso do modificador readonly

Essa é a forma mais simples de definir que a propriedade não pode mudar. Se alguém tentar, o compilador vai retornar erro:

interface Pedido {
  readonly id: number; // <-- não poderia ser modificado
  status: string;      
}

const meuPedido: Pedido = { id: 22, status: "Pendente" };

meuPedido.id = 23; // erro de compilação que bloqueia rodar o código
Enter fullscreen mode Exit fullscreen mode

Uso do utility type Readonly<T>

Se você quer que todas as propriedades de um tipo ou interface sejam imutáveis, você usa o Utility Type Readonly.

interface Settings {
  darkMode: boolean;
  language: string;
}

// transforma todas as chaves em 'readonly'
type ConfigApp = Readonly<Settings>;

config.darkMode = false; // vai retornar erro
Enter fullscreen mode Exit fullscreen mode

as const

Para configurações e valores que nunca devem mudar, o as const é o ideal. Ele não só torna o objeto readonly, mas também transforma os valores em Tipos Literais. Isso significa que o valor do type é o próprio tipo.

Como por exemplo:

const ERROR_CODES = {
    NOT_FOUND: 404,
    SERVER_ERROR: 500,
    UNAUTHORIZED: 401
} as const;

console.log("Objeto:", ERROR_CODES); // retorna o objeto acima
console.log("Tipo literal de not found:", ERROR_CODES.NOT_FOUND); // Tipo literal de not found:  404 
console.log("Tipo literal de server error:", ERROR_CODES.SERVER_ERROR); // Tipo literal de server error:  500 
Enter fullscreen mode Exit fullscreen mode

Como conclusão, nós podemos afirmar que, basicamente imutabilidade no JS é mais uma prática.

O TS não faz seu JavaScript se comportar como Rust ou C++. O que o TypeScript garante é a consistência e a segurança dos seus dados em tempo de desenvolvimento, impedindo que esses bugs cheguem ao ambiente de execução.

Em sistemas de grande escala onde a mutabilidade pode ser um pesadelo, saber desses pontos pode ter dar previsibilidade.

Top comments (0)