Typescript: Проверка шрифта теряет тип в for-of

Созданный на 8 нояб. 2016  ·  3Комментарии  ·  Источник: microsoft/TypeScript

Версия TypeScript: 2.0.8

Код

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

Скомпилировано с помощью cmd: tsc --noImplicitAny test.ts

Ожидаемое поведение:
Нет ошибок

Фактическое поведение:

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

Самый полезный комментарий

Это проблема анализа потока управления. Чтобы определить тип для ITEM нам нужно выяснить тип потока управления arg.arr . Это, в свою очередь, означает, что нам нужно рассмотреть конструкции, которые влияют на тип arg . Это включает в себя вызов otherFunc который выглядит так, как будто _ может_ быть предикатом определенного пользователем типа. Чтобы определить, является ли он _ предикатом типа, мы разрешаем выражение вызова, что влечет за собой разрешение выражений аргументов, что требует от нас знания типа ITEM . Это создает замкнутость, которую мы не можем разрешить, поэтому мы возвращаемся к неявному типу any .

Мы можем исправить это, если сначала логика распознавания предикатов типа определит тип функционального объекта и проверит все сигнатуры вызовов. Если ни один из них не является предикатом типа, определяемым пользователем, мы можем выручить раньше, не разрешая выражения аргументов вызова, что позволяет избежать цикличности.

Между тем, вы можете нарушить цикличность, просто добавив круглые скобки к arg в вызове otherFunc . Другими словами, измените вызов на otherFunc(ITEM, (arg)) . Это заставляет анализатор потока управления больше не рассматривать вызов как возможный вызов предиката определенного пользователем типа.

Все 3 Комментарий

Это проблема анализа потока управления. Чтобы определить тип для ITEM нам нужно выяснить тип потока управления arg.arr . Это, в свою очередь, означает, что нам нужно рассмотреть конструкции, которые влияют на тип arg . Это включает в себя вызов otherFunc который выглядит так, как будто _ может_ быть предикатом определенного пользователем типа. Чтобы определить, является ли он _ предикатом типа, мы разрешаем выражение вызова, что влечет за собой разрешение выражений аргументов, что требует от нас знания типа ITEM . Это создает замкнутость, которую мы не можем разрешить, поэтому мы возвращаемся к неявному типу any .

Мы можем исправить это, если сначала логика распознавания предикатов типа определит тип функционального объекта и проверит все сигнатуры вызовов. Если ни один из них не является предикатом типа, определяемым пользователем, мы можем выручить раньше, не разрешая выражения аргументов вызова, что позволяет избежать цикличности.

Между тем, вы можете нарушить цикличность, просто добавив круглые скобки к arg в вызове otherFunc . Другими словами, измените вызов на otherFunc(ITEM, (arg)) . Это заставляет анализатор потока управления больше не рассматривать вызов как возможный вызов предиката определенного пользователем типа.

@ahejlsberg
Спасибо за обходные скобки.
Я хочу в этом разобраться. PR - это приемлемо, не правда ли?

@arusakov Исправь сейчас в мастере!

Была ли эта страница полезной?
0 / 5 - 0 рейтинги