Executando verificação de segurança...
2

🧙‍♂️ Diferença entre Any e Unknown no Typescript

Você sabe a diferença entre any e unknown?

any e unknown são tipos bem parecidos e podem parecer que são até iguais, mas possuem suas diferenças.

A confusão que se tem sobre esses dois tipos vem do fato de que, se criarmos uma função que recebe dois parâmetros, um do tipo any e outro do tipo unknown, veremos que podemos passar qualquer variável para ambos os tipos sem erros.

const foo = (anyType: any, unknownType: unknown) => {};

foo({}, {});
foo(123, 456);
foo(null, null);
foo(
  () => {},
  () => {}
);

Mas é possível ver a diferença quando se usa essas variáveis.

Com any você pode atribuir qualquer tipo e usar como se fosse qualquer tipo. Já unknown você pode atribuir qualquer tipo, mas ao usar ele não é nenhum tipo e você precisará verificar qual é o tipo.

Uma variável do tipo any você pode ser usada como uma string ou como uma função e até mesmo como um objeto, mostrando que any é equivalente a todos os tipos.

const foo = (anyType: any, unknownType: unknown) => {
  const str1: string = anyType; // => ok
  anyType(); // => ok
  anyType.foo; // => ok
};

Já o unknown, mesmo podendo receber qualquer tipo, ele da erro quando se tenta usa-lo como qualquer tipo, portanto não se pode usa-lo como uma string, função, objeto ou qualquer outro tipo diferente de unknown.

const foo = (anyType: any, unknownType: unknown) => {
  const str1: string = anyType; // => ok
  anyType(); // => ok
  anyType.foo; // => ok

  const str2: string = unknownType; // => erro
  unknownType(); // => erro
  unknownType.foo; // => erro
};

Para você poder usar uma variável do tipo unknown, é preciso que se verifique o tipo antes. Para atribuir unknown para uma string, pode-se verificar utilizando typeof e ver se o tipo da variável é de fato string, e o mesmo pode ser feito para uma função.

const str2: string = unknownType; // => erro
if (typeof unknownType === "string") {
  const str2: string = unknownType; // => ok
}

unknownType(); // => erro
if (typeof unknownType === "function") {
  unknownType(); // => ok
}

Para verificar se uma variável é de um tipo mais especifico, como um objeto com algumas propriedades especificas, é necessário utilizar um user-defined type guard, que é uma função que o retorno dela define um type predicate, ou seja, define que uma variável é de um determinado tipo utilizando is.

interface Foo {
  foo: string;
}

// user-defined type guard      *type predicate*
const isFooType = (foo: unknown): foo is Foo => {
  return (foo as Foo)?.foo !== undefined;
};

unknownType.foo; // => erro
if (isFooType(unknownType)) {
  unknownType.foo; // => ok
}

Ao utilizar unknown ao invés de any você permite que seu código seja utilizado de forma muito mais segura.

Carregando publicação patrocinada...
1
1

Diferença sutil, mas importante.

Lembrando que tem outros tipos interessantes de se pensar também, como a diferença de uma função que retorna void e uma que retorna undefined. Sutil, mas diferente.