interface - Hva er fordelen med å bruke '--strictFunctionTypes' i Typescript?
Så vidt jeg forstår, forhindrer --strictFunctionTypes-kompilatoralternativet i Typescript at en veldig vanlig bruk av polymorfisme fungerer:
type Handler = (request: Request) => Response
const myHandler: Handler = (request: Request & { extraArg: boolean }) => {
return !!request.extraArg
}
Generelt antar jeg at alle kompilatorvalg i strict-familien har noen store fordeler, men i dette tilfellet ser jeg bare at det forhindrer en veldig logisk oppførsel fra å fungere.
Så hva er tilfellene hvor dette alternativet faktisk gir noen fordeler? Hvilke skadelige scenarier forhindrer det?
Svar #1
Det er faktisk veldig enkelt å forårsake en kjøretidsfeil uten strictFunctionTypes.
La oss vurdere følgende eksempel:
type Handler = (request: Request) => Response
const myHandler: Handler = (request: Request & { extraArg: string }) => {
// extraArg is required so need to check for null
request.extraArg.toUpperCase();
return null as any;
}
declare let r: Request; // comes from sowhere
myHandler(r); // no need to pass in the extraArg not required by the signature
Så i eksemplet ovenfor krever funksjonssignaturen en Request, så alt vi trenger å sende inn er en Request. Men implementeringen forventer å motta Request & { extraArg: string }, der extraArg er påkrevd, og få tilgang til det uten å måtte gjøre en sjekk (tross alt, hvis det er påkrevd, burde den som kaller ha sendt det inn).
Dette er typen feil strictFunctionTypes forhindrer. Hvis et argument i signaturen er av en basistype, mens implementeringen forventer en avledet type, er det ingen garanti for at implementeringen vil motta den avledede typen, ettersom signaturen kun krever at basistypen blir sendt inn
Svar #2
Dette alternativet fikser det som, etter min mening, er en feil i TypeScript-kompilatoren. Hvis det ikke er en feil, så var det bare en dårlig designbeslutning, og fremkomsten av et nytt kompilatoralternativ beviser poenget mitt. La oss starte med et eksempel, som standard vil følgende kode bli kompilert uten problemer:
// Focus all your attention on callback signature
// It has date parameter which is a union type
function getCurrentYear(callback: (date: string | number) => void) {
callback((Math.random() > 0.5) ? '2020' : 2020);
}
// note that we ignored the fact that in 50% cases our callback returns string type instead of number.
getCurrentYear((date: string) => {
console.log(date.charAt(0)); // in 50% it is RUNTIME ERROR
});
Slik at pilfunksjonen som sendes til getCurrentYear innsnevrer typen til "date"-parameteren, og TypeScript bryr seg ikke om det. Imidlertid vil det samme trikset i en annen kontekst med variabler, selv uten noen streng regel, gi en feil:
let x: string | number = (Math.random() > 0.5) ? '2020' : 2020;
const y: number = x; // COMPILE TIME ERROR
Dette gir mye mer mening, og å aktivere --strictFunctionTypes vil be en kompilator om å følge samme oppførsel i tilbakeringingsfunksjoner. Det vil definitivt hjelpe deg med å forhindre noen feil i et stort prosjekt.
Kilde :
https://medium.com/javascript-in-plain-english/what-are-these-strict-compiler-options-in-typescript-part-2-a7e974b13e54
