TypeScript Version: 2.0.8
Kode
// 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)) {
}
}
}
}
Disusun dengan cmd: tsc --noImplicitAny test.ts
Perilaku yang diharapkan:
Tidak ada kesalahan
Perilaku sebenarnya:
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.
Ini adalah masalah analisis aliran kontrol. Untuk menyimpulkan tipe untuk ITEM
kita perlu mencari tipe aliran kendali dari arg.arr
. Itu berarti kita perlu melihat konstruksi yang mempengaruhi tipe arg
. Ini termasuk panggilan ke otherFunc
yang sepertinya _bisa_ menjadi predikat tipe yang ditentukan pengguna. Untuk menentukan apakah itu _is_ predikat tipe, kita menyelesaikan ekspresi panggilan, yang memerlukan penyelesaian ekspresi argumen, yang mengharuskan kita untuk mengetahui tipe ITEM
. Ini menciptakan lingkaran yang tidak bisa kita selesaikan, jadi kita kembali ke tipe implisit any
.
Kita bisa memperbaikinya dengan meminta logika pengenalan tipe predikat terlebih dahulu menyelesaikan tipe objek fungsi dan memeriksa semua tanda tangan panggilan. Jika tidak satupun dari mereka adalah predikat tipe yang ditentukan pengguna, kita dapat menalangi lebih awal tanpa menyelesaikan ekspresi argumen panggilan, yang menghindari sirkularitas.
Sementara itu, Anda dapat memutus lingkaran hanya dengan menambahkan tanda kurung ke arg
dalam panggilan ke otherFunc
. Dengan kata lain, ubah panggilan menjadi otherFunc(ITEM, (arg))
. Hal ini menyebabkan penganalisis aliran kontrol tidak lagi mempertimbangkan panggilan tersebut sebagai kemungkinan pemanggilan predikat tipe yang ditentukan pengguna.
@ahejberg
Terima kasih atas solusi tanda kurung.
Saya ingin mencari tahu ini. PR bisa diterima, bukan?
@arusakov Perbaiki sekarang di master!
Komentar yang paling membantu
Ini adalah masalah analisis aliran kontrol. Untuk menyimpulkan tipe untuk
ITEM
kita perlu mencari tipe aliran kendali dariarg.arr
. Itu berarti kita perlu melihat konstruksi yang mempengaruhi tipearg
. Ini termasuk panggilan keotherFunc
yang sepertinya _bisa_ menjadi predikat tipe yang ditentukan pengguna. Untuk menentukan apakah itu _is_ predikat tipe, kita menyelesaikan ekspresi panggilan, yang memerlukan penyelesaian ekspresi argumen, yang mengharuskan kita untuk mengetahui tipeITEM
. Ini menciptakan lingkaran yang tidak bisa kita selesaikan, jadi kita kembali ke tipe implisitany
.Kita bisa memperbaikinya dengan meminta logika pengenalan tipe predikat terlebih dahulu menyelesaikan tipe objek fungsi dan memeriksa semua tanda tangan panggilan. Jika tidak satupun dari mereka adalah predikat tipe yang ditentukan pengguna, kita dapat menalangi lebih awal tanpa menyelesaikan ekspresi argumen panggilan, yang menghindari sirkularitas.
Sementara itu, Anda dapat memutus lingkaran hanya dengan menambahkan tanda kurung ke
arg
dalam panggilan keotherFunc
. Dengan kata lain, ubah panggilan menjadiotherFunc(ITEM, (arg))
. Hal ini menyebabkan penganalisis aliran kontrol tidak lagi mempertimbangkan panggilan tersebut sebagai kemungkinan pemanggilan predikat tipe yang ditentukan pengguna.