TypeScript-Version: 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)) {
}
}
}
}
Kompiliert mit cmd: tsc --noImplicitAny test.ts
Erwartetes Verhalten:
Keine Fehler
Tatsächliches Verhalten:
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.
Dies ist ein Problem bei der Kontrollflussanalyse. Um einen Typ für ITEM
abzuleiten, müssen wir den Kontrollflusstyp von arg.arr
herausfinden. Das bedeutet wiederum, dass wir uns Konstrukte ansehen müssen, die sich auf den Typ von arg
auswirken. Dies schließt den Aufruf von otherFunc
der so aussieht, als ob es sich um ein benutzerdefiniertes Prädikat handeln könnte. Um festzustellen, ob es sich um ein Typprädikat handelt, lösen wir den Aufrufausdruck auf, bei dem die Argumentausdrücke aufgelöst werden. Dazu müssen wir den Typ von ITEM
. Dies erzeugt eine Zirkularität, die wir nicht auflösen können, sodass wir auf einen impliziten any
-Typ zurückgreifen.
Wir können dies beheben, indem die Erkennungslogik für Typprädikate zuerst den Typ des Funktionsobjekts auflöst und alle Aufrufsignaturen untersucht. Wenn es sich bei keinem von ihnen um benutzerdefinierte Prädikate handelt, können wir frühzeitig aussteigen, ohne die Aufrufargumentausdrücke aufzulösen, wodurch die Zirkularität vermieden wird.
In der Zwischenzeit können Sie die Zirkularität einfach durch Hinzufügen von Klammern zu arg
im Aufruf von otherFunc
durchbrechen. Mit anderen Worten, ändern Sie den Anruf in otherFunc(ITEM, (arg))
. Dies führt dazu, dass der Kontrollflussanalysator den Aufruf nicht mehr als möglichen benutzerdefinierten Prädikataufruf vom Typ betrachtet.
@ahejlsberg
Vielen Dank für die Problemumgehung in Klammern.
Ich möchte das herausfinden. PR ist akzeptabel, nicht wahr?
@arusakov Jetzt im Master
Hilfreichster Kommentar
Dies ist ein Problem bei der Kontrollflussanalyse. Um einen Typ für
ITEM
abzuleiten, müssen wir den Kontrollflusstyp vonarg.arr
herausfinden. Das bedeutet wiederum, dass wir uns Konstrukte ansehen müssen, die sich auf den Typ vonarg
auswirken. Dies schließt den Aufruf vonotherFunc
der so aussieht, als ob es sich um ein benutzerdefiniertes Prädikat handeln könnte. Um festzustellen, ob es sich um ein Typprädikat handelt, lösen wir den Aufrufausdruck auf, bei dem die Argumentausdrücke aufgelöst werden. Dazu müssen wir den Typ vonITEM
. Dies erzeugt eine Zirkularität, die wir nicht auflösen können, sodass wir auf einen implizitenany
-Typ zurückgreifen.Wir können dies beheben, indem die Erkennungslogik für Typprädikate zuerst den Typ des Funktionsobjekts auflöst und alle Aufrufsignaturen untersucht. Wenn es sich bei keinem von ihnen um benutzerdefinierte Prädikate handelt, können wir frühzeitig aussteigen, ohne die Aufrufargumentausdrücke aufzulösen, wodurch die Zirkularität vermieden wird.
In der Zwischenzeit können Sie die Zirkularität einfach durch Hinzufügen von Klammern zu
arg
im Aufruf vonotherFunc
durchbrechen. Mit anderen Worten, ändern Sie den Anruf inotherFunc(ITEM, (arg))
. Dies führt dazu, dass der Kontrollflussanalysator den Aufruf nicht mehr als möglichen benutzerdefinierten Prädikataufruf vom Typ betrachtet.