typeguards - Typescript Type Guards og fet pil-funksjon
Bør ikke dette kompileres riktig? Jeg får en feil "Egenskapen 'hello' eksisterer ikke på typen 'object'." på den uthevede linjen.
Jeg kan få tilgang til g.hello utenfor fat arrow-funksjonen uten problemer.
class Test {
constructor() {
}
hello() : string {
return "Hello";
}
}
let g : object;
if (g instanceof Test) {
() => {
g.hello(); ////// ERROR HERE /////
};
}
Svar #1
Innstrammingen som en typebeskyttelse gjør på en variabel (eller noe annet) vil ikke krysse funksjonsgrenser. Dette er en designbegrensning.
En måte å omgå dette problemet på er å tilordne g til en ny variabel, som vil få sin type utledet basert på innsnevringen. Å få tilgang til den nye variabelen i pilfunksjonen vil fungere som forventet:
class Test {
constructor() {
}
hello() : string {
return "Hello";
}
}
let g : object;
if (g instanceof Test) {
const gTest = g;
() => {
gTest.hello();
};
}
En annen måte å omgå dette problemet på hvis g ikke endres, er å erklære g med const. Dette vil la kompilatoren bevare innsnevringen:
let g : object;
if (g instanceof Test) {
const gTest = g;
() => {
gTest.hello();
};
}
Lekeromlenke
Svar #2
let + pilfunksjon
class Test {
constructor() {
}
hello() : string {
return "Hello";
}
}
declare let g : object;
if (g instanceof Test) {
() => {
g.hello(); // error
};
}
g er en Test når funksjonen er definert, men g kanskje ikke er Test når funksjonen kjøres.
const + pilfunksjon
class Test {
constructor() {
}
hello() : string {
return "Hello";
}
}
declare const g : object;
if (g instanceof Test) {
() => {
g.hello(); // ok
};
}
g er uforanderlig, g er alltid en Test etter at funksjonen er definert.
const + vanlig funksjon
class Test {
constructor() {
}
hello() : string {
return "Hello";
}
}
declare const g : object;
if (g instanceof Test) {
function f() {
g.hello(); // error
};
}
Innen underliggende implementering er vanlig funksjon f definert av ES5 var, i stedet for ES6 let. Variabelhoisting flytter deklarasjonen av f, når g kanskje ikke er en Test.
