This is the first day of my participation in Gwen Challenge.
Typescript extends the syntax and semantics of typing to javascript, making JS code type safe at the statically typed language level. Type insafety problems that were previously only found at runtime can now be found at compile time, so large projects are increasingly written in typescript. In addition, typescript can work with ides to do better intelligent hints, which is another reason to use typescript.
Type-safe: If a variable of a type is assigned to a value of incompatible types, it is type-unsafe, and if an object of a type calls a method it does not have, it is type-unsafe. Otherwise, it’s type safety. Type safety means that assignment of variables and function calls to objects are within the scope of type support.
Initially, typescript code can only be compiled with the built-in TyepScript Compiler (TSC). Compiling different versions of typescript code requires different versions of TSC, and tsconfig.json is configured to specify how to compile.
But there are problems with TSC compiling TS code as JS:
TSC does not support much of the draft syntax that is supported through the Babel plug-in, so many project toolchains compile TS code once in TSC and then again by Babel. This compilation link is long, and the generated code is not compact enough.
So typescript worked with the Babel team to support typescript compilation in Babel7, with plugins specifying compilation of TS syntax. For example, in the API, this is used:
const parser = require('@babel/parser');
parser.parse(sourceCode, {
plugins: ['typescript']});Copy the code
The plugin is the result of a year-long collaboration between the typescript team and the Babel team.
But does this plug-in really support all typescript code? The answer is no.
Let’s take a look at what TS syntax Babel doesn’t support and why.
Does Babel compile all typescript code?
The compilation process for Babel looks like this:
- Parser: Parses source code into an AST
- Traverse: Traverse the AST, generate scope information and path, call various plug-ins to convert the AST
- Generator: Prints the transformed AST as object code and generates sourcemap
Typescript Compiler works like this:
- Scanner + Parser: Word segmentation and ast assembly, from source code to AST process
- Binder + Checker: Generates scope information for type inference and checking
- Transform: Converts the AST that has been type checked
- Emitter: Printing ast into object code, generating Sourcemap and type declaration files (depending on configuration)
The compile phase of Babel is similar to the compile phase of TSC, except that TSC has an extra checker and the rest is the same.
- Babel’s Parser corresponds to TSC’s scanner + Parser
- Babel traverse stage corresponds to TSC’s Binder + Transform
- Babel’s generator corresponds to TSC’s Emitter
Is it possible to implement Checker with Traverse with Babel plugins?
The answer is no.
Because TSC type check needs to get the type information of the whole project, need to do type introduction, multiple files of namespace, enum, interface, etc., and Babel is compiled by a single file, will not parse the information of other files. So you can’t do the same type checking as TSC.
Babel is unable to do TSC type checking due to the difference between parsing multiple files during compilation and only one file during compilation.
So how does Babel compile typescript?
Babel can parse TS code into an AST and does no type checking. It simply removes the type information and prints it as object code.
This results in some TS syntax that Babel does not support:
-
Const enum not supported. Const enum replaces a reference to an enum with a specific value at compile time, requiring parsing of type information. Babel does not parse and therefore does not support this. We can use plug-ins to convert const enum to enum.
-
Namespace is partially supported. Cross-file merging of namespaces is not supported, and exporting non-const values is not supported. This is also because Babel does not parse type information and is single-file compiled.
The above two types are not supported because of different compilation methods.
-
Export = import = This TS-specific syntax is not supported and can be converted to ESM through plug-ins
-
If JSX compilation is enabled, the <string> aa type assertion is not supported. Aa as string is used instead. This is because the two grammars conflict, and in both syntax plug-ins (JSX, typescript) the way to resolve the conflict is to use AS instead.
These four are the ts syntax that Babel doesn’t support, but they don’t really matter.
Conclusion: Babel doesn’t compile all typescript code, but all but two features of namespace do.
Babel compiles typescript code, so why compile with Babel?
Why compile typescript code with Babel?
Compiling typescript code with Babel has three major advantages:
The product has a smaller volume
tsc
How does TSC configure the build target?
Configure target in compilerOptions. Target sets the target language version
{
compilerOptions: {
target: "es5" / / es3, es2015}}Copy the code
How does typescript introduce polyfill?
Introduce core-js in the entry file.
import 'core-js';
Copy the code
babel7
How does Babel7 configure the build target?
Specify targets in preset-env, specify the target running environment (browser, Node) version directly, or specify the query string, browserslist finds out the specific version.
{
presets: [["@babel/preset-env",
{
targets: {
chrome: 45}}]]}Copy the code
{
presets: [["@babel/preset-env",
{
targets: "last 1 version,> 1%,not dead"}}]]Copy the code
How does Babel7 introduce Polyfill?
Targets should be specified, which polyfill should be used (corejs2 or corejs3), and how to introduce (entry is introduced in the entry, usage is introduced separately in each module).
{
presets: [["@babel/preset-env",
{
targets: "last 1 version,> 1%,not dead".corejs: 3.useBuiltIns: 'usage'}}]]Copy the code
@babel/compat-data to do syntactic conversion and API polyfill:
First check the supported version of the target environment based on the targets, and then filter the supported features from all features based on the version of the target environment. The remaining features are not supported. Just convert and polyfill these features.
Babel can also convert global Corejs import into modular import via @babel/ plugin-transform-Runtime.
Clearly, compiling typescript with Babel has two product-wise advantages:
- Can do more accurate on-demand compilation and polyfill, product size is smaller
- The introduction of polyfill into modularity through plug-ins without polluting the global environment
In terms of products, Babel wins.
Supported language features
Typescript supports many ES features by default, but doesn’t support presets. Babel’s Preset -env supports all standard features, and more presets can be supported through proposal.
{
plugins: ['@babel/proposal-xxx'].presets: ['@babel/presets-env', {... }}]Copy the code
In terms of supported language features, Babel wins.
Compilation speed
TSC will conduct type check during compilation. Type check needs to synthesize the type information of multiple files, and it takes time to derive the type from AST. Babel does not perform type check, so the compilation speed is much faster.
In terms of compile speed, Babel wins.
Overall, Babel wins in terms of compilation product size (mainly), supported language features, and compilation speed.
But Babel doesn’t do type checking, so how?
Babel and TSC
Babel compiles to produce smaller artifacts, has faster compilation times, and has more feature support, so we choose to compile typescript code with Babel. However, type checking is also needed, and NPM scripts can be configured with a command:
{
"scripts": {
"typeCheck": "tsc --noEmit"}}Copy the code
NPM run typeCheck will do the trick if you need to do a typeCheck, but it’s best to do a mandatory typeCheck in a git commit hook (via husky configuration).
conclusion
Typescript extends static typing support to JS, allowing code to detect errors at compile time such as assignment type mismatches and calling missing methods, ensuring type-safety.
Babel7 now compiles typescript code in addition to TSC, the result of a year of collaboration between the two teams.
Babel, however, does not have the same effect as TSC because of its single-file nature. It does not support several features (mainly merging namespace across files and exporting nonconst values), but the impact is minor and overall usable.
To compile the code, TSC –noEmit should be used for type checking.
Babel compiles TS code and has many advantages over TSC: it is smaller in size, supports more features, and compiles faster. Compiling typescript with Babel is a better option.
For more information, see the Gold Digger’s Babel Tutorial.