Typescript: O verificador de tipo perde o tipo em para-de

Criado em 8 nov. 2016  ·  3Comentários  ·  Fonte: microsoft/TypeScript

Versão TypeScript: 2.0.8

Código

// test.ts
interface Type {
  type: number;
}

interface TypeExt extends Type {
  arr: Type[];
}

const guard = (arg: Type): arg is TypeExt => arg.type === 1;
const otherFunc = (arg1: Type, arg2: TypeExt): void => {};

export function y(arg: Type): void {
  if (guard(arg)) {
    for (const ITEM/* error is here */ of arg.arr) {
      if (otherFunc(ITEM, arg)) {
      }
    }
  }
}

Compilado com cmd: tsc --noImplicitAny test.ts

Comportamento esperado:
Sem erros

Comportamento real:

test.ts(14,16): error TS7022: 'ITEM' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
Bug Fixed

Comentários muito úteis

Este é um problema de análise de fluxo de controle. Para inferir um tipo para ITEM , precisamos descobrir o tipo de fluxo de controle de arg.arr . Isso, por sua vez, significa que precisamos olhar as construções que afetam o tipo de arg . Isso inclui a chamada para otherFunc que parece que _pode_ ser um predicado de tipo definido pelo usuário. Para determinar se _é_ um predicado de tipo, resolvemos a expressão de chamada, que envolve a resolução das expressões de argumento, o que exige que conheçamos o tipo de ITEM . Isso cria uma circularidade que não podemos resolver, portanto, recorremos a um tipo any implícito.

Podemos corrigir isso fazendo com que a lógica de reconhecimento de predicado de tipo resolva primeiro o tipo do objeto de função e examine todas as assinaturas de chamada. Se nenhum deles forem predicados de tipo definidos pelo usuário, podemos sair antes sem resolver as expressões de argumento de chamada, o que evita a circularidade.

Enquanto isso, você pode quebrar a circularidade simplesmente adicionando parênteses a arg na chamada para otherFunc . Em outras palavras, mude a chamada para otherFunc(ITEM, (arg)) . Isso faz com que o analisador de fluxo de controle não considere mais a chamada como uma possível invocação de predicado de tipo definido pelo usuário.

Todos 3 comentários

Este é um problema de análise de fluxo de controle. Para inferir um tipo para ITEM , precisamos descobrir o tipo de fluxo de controle de arg.arr . Isso, por sua vez, significa que precisamos olhar as construções que afetam o tipo de arg . Isso inclui a chamada para otherFunc que parece que _pode_ ser um predicado de tipo definido pelo usuário. Para determinar se _é_ um predicado de tipo, resolvemos a expressão de chamada, que envolve a resolução das expressões de argumento, o que exige que conheçamos o tipo de ITEM . Isso cria uma circularidade que não podemos resolver, portanto, recorremos a um tipo any implícito.

Podemos corrigir isso fazendo com que a lógica de reconhecimento de predicado de tipo resolva primeiro o tipo do objeto de função e examine todas as assinaturas de chamada. Se nenhum deles forem predicados de tipo definidos pelo usuário, podemos sair antes sem resolver as expressões de argumento de chamada, o que evita a circularidade.

Enquanto isso, você pode quebrar a circularidade simplesmente adicionando parênteses a arg na chamada para otherFunc . Em outras palavras, mude a chamada para otherFunc(ITEM, (arg)) . Isso faz com que o analisador de fluxo de controle não considere mais a chamada como uma possível invocação de predicado de tipo definido pelo usuário.

@ahejlsberg
Obrigado pela solução alternativa entre parênteses.
Eu quero descobrir isso. RP é aceitável, não é?

@arusakov Fix now in master!

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

MartynasZilinskas picture MartynasZilinskas  ·  3Comentários

bgrieder picture bgrieder  ·  3Comentários

fwanicka picture fwanicka  ·  3Comentários

jbondc picture jbondc  ·  3Comentários

Antony-Jones picture Antony-Jones  ·  3Comentários