Pesquisa de site

Por que o TypeScript não restringe o tipo any neste guard de tipo?


O seguinte exemplo me confunde:

class MyClass
{
    public MyProp = "";
}

var object: any = null;

if (object instanceof MyClass)
    console.log(object.MyProp, object.NonExistant); // <-- No error, no intellisense

Por que o guarda de tipo não está me dando o tipo correto dentro do contexto verificado?

Resposta #1

Guardiões de tipo definidos pelo usuário e guardiões de tipo instanceof não reduzem tipos que são any (incluindo tipos de união e interseção com any).

A única coisa que irá restringir um any em um guarda de tipo é usar a verificação typeof e verificar os primitivos string, bool e number:

var something: any;
if (typeof something === "string")
{
    something.NonExistant(); // <- Error, does not exist on `string`
    something.substr(0, 10); // <- Ok
}

Os outros valores genéricos de typeof, function, object e undefined, não estreitam any se alguém tentar usá-los como no exemplo acima.

Também existe uma questão em aberto para tornar possível restringir any para tipos primitivos dentro de guardas de tipo definidos pelo usuário, planejada para o TS 2.0.

Esta é uma decisão de design consciente e não um bug

A motivação principal parece ter sido que proteger um tipo geralmente restringe o tipo possível e nos dá acesso a mais propriedades que podemos ter certeza de que existem dentro do contexto verificado. Mas no caso de proteger o tipo especial any, já temos acesso a todos os membros que poderiam existir, então fazer proteção de tipo em um any, como você esperava no seu exemplo, na verdade nos limitaria.

Outra motivação também parece ser que há muito código ruim por aí que quebraria se o TypeScript restringisse any assim como os outros tipos.

Solução alternativa

Se você tiver uma variável que pode ser uma instância de uma classe arbitrária, use o tipo Object ou unknown em vez de any e a proteção de tipo funcionará como esperado.

Artigos relacionados