Typescript: Le vérificateur de type perd le type dans for-of

Créé le 8 nov. 2016  ·  3Commentaires  ·  Source: microsoft/TypeScript

Version de TypeScript: 2.0.8

Code

// 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)) {
      }
    }
  }
}

Compilé avec cmd: tsc --noImplicitAny test.ts

Comportement prévisible:
Aucune erreur

Comportement réel:

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

Commentaire le plus utile

Il s'agit d'un problème d'analyse de flux de contrôle. Afin de déduire un type pour ITEM nous devons déterminer le type de flux de contrôle de arg.arr . Cela signifie à son tour que nous devons examiner les constructions qui affectent le type de arg . Cela inclut l'appel à otherFunc qui semble être un prédicat de type défini par l'utilisateur. Afin de déterminer s'il _est_ un prédicat de type, nous résolvons l'expression d'appel, ce qui implique la résolution des expressions d'argument, ce qui nous oblige à connaître le type de ITEM . Cela crée une circularité que nous ne pouvons pas résoudre, nous revenons donc à un type implicite any .

Nous pouvons résoudre ce problème en demandant à la logique de reconnaissance de prédicat de type de résoudre d'abord le type de l'objet fonction et d'examiner toutes les signatures d'appel. Si aucun d'entre eux n'est un prédicat de type défini par l'utilisateur, nous pouvons renflouer tôt sans résoudre les expressions d'argument d'appel, ce qui évite la circularité.

Pendant ce temps, vous pouvez briser la circularité simplement en ajoutant des parenthèses à arg dans l'appel à otherFunc . En d'autres termes, changez l'appel en otherFunc(ITEM, (arg)) . Cela fait que l'analyseur de flux de contrôle ne considère plus l'appel comme un possible appel de prédicat de type défini par l'utilisateur.

Tous les 3 commentaires

Il s'agit d'un problème d'analyse de flux de contrôle. Afin de déduire un type pour ITEM nous devons déterminer le type de flux de contrôle de arg.arr . Cela signifie à son tour que nous devons examiner les constructions qui affectent le type de arg . Cela inclut l'appel à otherFunc qui semble être un prédicat de type défini par l'utilisateur. Afin de déterminer s'il _est_ un prédicat de type, nous résolvons l'expression d'appel, ce qui implique la résolution des expressions d'argument, ce qui nous oblige à connaître le type de ITEM . Cela crée une circularité que nous ne pouvons pas résoudre, nous revenons donc à un type implicite any .

Nous pouvons résoudre ce problème en demandant à la logique de reconnaissance de prédicat de type de résoudre d'abord le type de l'objet fonction et d'examiner toutes les signatures d'appel. Si aucun d'entre eux n'est un prédicat de type défini par l'utilisateur, nous pouvons renflouer tôt sans résoudre les expressions d'argument d'appel, ce qui évite la circularité.

Pendant ce temps, vous pouvez briser la circularité simplement en ajoutant des parenthèses à arg dans l'appel à otherFunc . En d'autres termes, changez l'appel en otherFunc(ITEM, (arg)) . Cela fait que l'analyseur de flux de contrôle ne considère plus l'appel comme un possible appel de prédicat de type défini par l'utilisateur.

@ahejlsberg
Merci pour la solution de contournement entre parenthèses.
Je veux comprendre cela. Les relations publiques sont acceptables, n'est-ce pas?

@arusakov Fix maintenant dans Master!

Cette page vous a été utile?
0 / 5 - 0 notes