mål - Hva vil Typescript transpilere når målet er ES5/ES3?
Jeg prøver å forstå når Typescript-kompilatoren vil transpilere kode for å gjøre den kompatibel med min spesifiserte mål-ECMAScript-versjon (ES5 eller ES3).
For eksempel vil TSC transpile for(var int of intArray) uten problemer, men det transpilerer ikke Number.isInteger() (som er en ES6-funksjon, ifølge w3schools).
Number.isInteger() støttes ikke i IE < 11.0, så dette er et problem. Visual Studio (og VS Code) gir ikke advarsler om inkompatibilitet, og det blir ikke transpileret.
Hva kan jeg forvente å få transpillert, og hva ikke? Jeg forventet opprinnelig at alt ville bli transpillert, slik at jeg ikke måtte holde styr på ting som dette, men det ser ikke ut til å være tilfelle.
Svar #1
TypeScript transpilerer men polyfiller ikke. Så en måte å tenke på det på er at alt som ikke er gyldig syntaks i din target vil bli transpilert til gyldig syntaks. For eksempel, når du bruker class-nøkkelordet med målet ditt satt til ES5, vil det transpileres slik:
class Greeter {
}
til dette:
var Greeter = /** @class */ (function () {
function Greeter() {
}
return Greeter;
}());
(Du kan leke mer med dette her.)
På den annen side legger det ikke til manglende funksjonalitet, som du må polyfille selv. Number.isInteger() er gyldig ES5-syntaks, det er bare ikke funksjonalitet som eksisterer i ES5. Du kan polyfille dette selv ved å importere babel-polyfill (som bruker core-js under panseret) eller bruke en tjeneste som polyfill.io.
Merk: ikke forveksle lib-alternativet med polyfills. Dette erstatter ikke funksjoner med polyfills. Det forteller bare TypeScript å oppføre seg som om funksjoner fra disse ES-versjonene er til stede, slik at det vil typekontrollere dem riktig. Du må fortsatt håndtere polyfill-delen selv for de nettleserne du støtter. Hvis du ikke angir de riktige lib-ene, vil TypeScript klage på at det ikke vet hva Number.isInteger() representerer.
Jeg er ikke kjent med en omfattende liste over hvilke funksjoner TypeScript transpilerer, men du kan se en tabell for TypeScript+core-js polyfiller her. Mer lesing om polyfiller vs transpiling her.
Svar #2
Kompilatoren støtter funksjoner basert på biblioteket du sier den skal bruke.
Det finnes to måter å kontrollere hvilket bibliotek kompilatoren vil bruke, ved å bruke kompilatoralternativene target og lib.
Som det står skrevet i lenken ovenfor:
Hvis --lib ikke er spesifisert, blir et standardbibliotek injisert. Standardbiblioteket som injiseres er:
► For --target ES5: DOM, ES5, ScriptHost
► For --target ES6: DOM, ES6, DOM.Iterable, ScriptHost
Alle de forskjellige bibliotekene er en del av prosjektet.
Hvis du sikter mot es3 eller es5, kan du ikke bruke Number.isInteger() siden det (som du nevnte) er en es6-funksjon.
Hvis du har en polyfill for det, kan du fortsatt sikte mot es5 med es6-biblioteket:
--target es5 --lib DOM,ES6,ScriptHost
Eller du kan bare kopiere definisjonen for lib.es6.d.ts:
interface NumberConstructor {
isInteger(number: number): boolean;
}
Grunnen til at du kan bruke ting som let, const, for/of uavhengig av målet, er at kompilatoren vet hvordan den kan produsere tilsvarende kode selv når funksjonen ikke støttes for det valgte målet.
For eksempel:
const arr = [1, 2, 3];
for (let num of arr) {}
Komplilert til:
var arr = [1, 2, 3];
for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) {
var num = arr_1[_i];
}
Hvis ingen mål er spesifisert.
Som du kan se, blir const og let gjort om til var, og for/in blir gjort om til en vanlig for.
Number.isInteger() er noe annet, det er en funksjonalitet som ikke eksisterer i visse mål, som Promise og 'Symbol`.
Kompilatoren vil ikke legge til polyfill, det er opp til deg å legge den til og deretter fortelle kompilatoren at den er der.
