TypeScript With Babel: A Beautiful Marriage

Thank youTypeScript plug-in for Babel(@babel/preset-typescript),TypeScriptIt’s never been easier, and this is the result of a year-long official collaboration between the TypeScript and Babel teams. This article provides four reasons why TypeScript and Babel are a perfect couple, and a 10-minute step-by-step guide to upgrading to TypeScript.

Huh? What? Why is that?

I didn’t understand the need this new preset was supposed to solve at first.

Aren’t Babel and TypeScript two very different things? How does Babel handle TypeScript type checking? TypeScript already prints ES5 like Babel, so what’s the purpose? Does merging Babe and TypeScript make things more complicated?

After an hour of research, MY conclusion is that TypeScript and Babel make a beautiful marriage.

Let me show you.

1) You already use Babel (or should)

You must fall into one of three categories:

  1. Babel is already in use, and if not directly, Webpack will be*.jsFiles are provided to Babel (many framework templates fall into this category, includingcreat-react-app).
  2. Use TypeScript but not Babel. Consider adding Babel to your project’s library, which will bring many unique features. Read on.
  3. Not using Babel at all? So now it’s time to jump on board Babel.

Write modern JavaScript without throwing any errors

Need to run JavaScript code in an older browser? No problem. Babel will transform the code and fix everything. Get straight to the latest and greatest features and don’t worry about anything.

The TypeScript compiler has a similar capability by setting the target value to ES5 or ES6. But Babel uses babel-preset-env to improve this feature, and instead of locking in a specific set of JavaScript features (ES5, ES6, etc.), just list the environments that need to be supported:

"targets": {
    "browsers": ["last 2 versions"."safari >= 7"]."node": "6.10"
}
Copy the code

Babel uses compat-table to check for JavaScript features that need to be converted, as well as polyfills that are required for the specified target environment.

creat-react-appAn interesting technique used: Compiling against the latest browsers during development (for faster compilation) and multiple browsers during production release (for compatibility), Nice~

Babel is super configurable

Want JSX? The Flow? TypeScript? Babel handles them by installing plug-ins. There are quite a few official plug-ins to choose from, covering most of the upcoming JavaScript syntax, as well as quite a few third-party plug-ins: improved Lodash Import, enhanced console.log, or clean console.log. You can find more plug-ins in the list of awesome- Babel.

Be careful, however, that TypeScript may not be able to parse plug-ins that change the syntax significantly. For example, there is a Babel plug-in: @babel/ plugin-proposal-option-chaining that enables the much anticipated alternative chain proposal.

const obj = {
    foo: {
        bar: {
            baz: 42}}};constbaz = obj? .foo? .bar? .baz;/ / 42

constsafe = obj? .qux? .baz;// undefined
Copy the code

Unfortunately, TypeScript doesn’t understand this coming syntax.

But no pressure, there are alternatives…

Babel Macros

I don’t know if you’ve heard of Kent C Dodds, who created a game-changing plug-in for Babel: Babel-plugin-Macros.

Instead of adding plug-ins directly to the Babel Config file, it installs macros as dependencies and imports them into the code. While Babel is compiling, macros come into play and modify the code.

For example, before the optional chain feature is officially added to the standard, we can use IDX. macro to achieve the same effect.

import idx from 'idx.macro';

const friends = idx(
	props,
	_= > _.user.friends[0].friends
);
Copy the code

The compiled:

const friends =
	props.user == null ? props.user :
	props.user.friends == null ? props.user.friends :
	props.user.friends[0] = =null ? props.user.friends[0] :
	props.user.friends[0].friends
Copy the code

The Babel Macro is a fairly new concept, but it’s quickly catching on. Especially if you log in to create-React-app V2.0, the CSS in JS includes styled- JSX, Styled – Components, and emotion. Porting Webpack plugins: raw-loader, URl-loader and filesize-loader. More are listed on awesome-babel-Macros.

Best of all, unlike Babel, all Babel Macros are compatible with TypeScirpt. They can still help reduce runtime dependencies, avoid client-side calculations, and catch exceptions ahead of time at build time. Check out this post for details.

The figure above illustrates a better console.log:scope.macro

2) It’s easier to manage just one compiler

TypeScirpt needs its own compiler because it provides excellent type checking.

In the Dark Days (before Babel 7)

Connecting two independent compilers (TypeScript and Babel) in tandem is not an easy task. The compilation process becomes TS > TS compiler > JS > Babel > JS (again).

Webpack is often used to solve this problem by tweaking the configuration of Webpack. Feed *.ts to TypeScript, and then feed Babel the result of the run. But which TypeScript loader to use? Two very popular options are TS-loader and awesome-typescript-loader. Awesome-typescript-loader’s readme. md mentions that it can be slow in some workloads and recommends using TS-Loader with HappyPack or Threadloader. The readme. md file of ts-loader is recommended to use a combination of fork-ts-checker-webpack-plugin, HappyPack, Thread-loader, and/or cache-loader.

Enough is enough. This is what engulfs most students, and one of the reasons people label TypeScript “too hard.” I don’t blame you.

The Day of Light (Babel 7)

Wouldn’t it be nice to have only one JavaScript compiler? Whether the code has ES2015 features, JSX, TypeScript, or some other crazy customization — the compiler knows what to do.

I was just describing Babel.

By allowing Babel to work as the only compiler, it’s no longer necessary to use some complicated Webpack magic to manage, configure, or merge two compilers.

It also streamlines the entire JavaScript ecosystem. Replaces ESLint, test Runner, build system, and different compilers provided by development templates that only need to support Babel. Babel is then configured to handle specific requirements. Say goodbye to TS-Loader, TS-Jest, TS-karma, create-react-app-typescript, etc. Use Babel instead. Babel support is everywhere, check it outBabel setupPage:

3) Faster compilation

How does Babel handle TypeScript? It removes TypeScript.

Yes, it removes all TypeScript, converts it to “regular” JavaScript, and continues to use it the way it pleases.

It sounds ridiculous, but this implementation has two very powerful advantages.

First advantage: ⚡️ is as fast as lightning ⚡️

Most TypeScript developers experience very slow compilations in Devlement/Watch mode. You’re typing code, saving files, and waiting for a long time… Finally, you see what you changed. Uh-oh, misspelled, modified, saved, and… Enough is enough! Not only is it annoyingly slow, it also frustrates your programming motivation.

We can’t blame the TypeScript compiler for doing too much work. It scans the type definition files (*.d.ts), including node_modules, to make sure you use them correctly in your code. This is why many people break TypeScript type checking into a separate process. However, the Babel + TypeScript package still provides faster compilation thanks to Babel’s excellent caching and single-file distribution architecture.

So if Babel strips TypeScript of its code, what’s the point of writing TypeScript? This brings a second advantage…

4) Check for type errors only when you are ready

Now you’re throwing some code together, and you can’t wait to find a solution to see if your idea works. When you save the file, TypeScript yells at you:

“No! I’m not going to compile this thing! Your code is abnormal in 42 different files!”

Yeah, you know there’s something wrong with it. There may have been exceptions in several unit tests. But you might just want to do an experiment here. The constant type safety checking can sometimes be annoying.

This is the second advantage of Babel stripping TypeScript from compilation. Write, save, and it compiles quickly (fast) with no type-safety checks. This gives you the freedom to experiment with solutions before you’re ready to check for code errors.

So how do you check for type errors? Add a NPM run check-types script to invoke the TypeScript compiler. I adjusted my NPM test command to check first and then continue running the unit tests.

It wasn’t a perfect marriage

According to the project announcement, there are four TypeScript features that don’t compile in Babel because of its single-file emission architecture.

But don’t worry, it’s not too bad. TypeScript also warns of these problems when the configuration option isolatedModules is enabled.

1) the Namespace

Solution: Don’t use it! They are out of date. Switch to the standard ES6 module (import/export) and don’t use Namesapce in the recommended TSLint rules.

2) use<newtype>xSyntactic conversion type

Solution: Use x as newtype instead.

3)Const enumeration

This pot does not have to shake, can only use the conventional enumeration, looking forward to the future can support.

4) Legacy import/export syntax

For example: import foo = require(…) And export = foo.

In all my years of writing TypeScript, I’ve never written like this. Who wrote that? Don’t ever do that again!

OK, ready to try writing TypeScript using Babel

Get started! It only takes 10 minutes.

Assuming you have Babel 7 installed, if not, check out the Babel Migration guide.

1) Rename.js to.ts

Suppose the file is stored in the/SRC directory:

find src -name "*.js" -exec sh -c 'mv "$0" "${0%.js}.ts"' {} ;
Copy the code

Add TypeScript to Babel

Install several dependencies:

npm install --save-dev @babel/preset-typescript @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread
Copy the code

Babel configuration file (.babelrc or babel.config.js) :

{
	"presets": [
		"@babel/typescript"]."plugins": [
		"@babel/proposal-class-properties"."@babel/proposal-object-rest-spread"]}Copy the code

TypeScript has several additional features that Babel needs to know about (via the two plug-ins listed above).

By default, Babel looks for.js files. Unfortunately, you can’t configure this in Babel’s config file.

If using Babel CLI, add — Extensions ‘.ts’.

If using Webpack, add ‘ts’ to the resolve.Extensions array.

3) Add the ‘check-type’ command

Add to package.json:

"scripts": {
	"check-types": "tsc"
}
Copy the code

This command simply invokes the TypeScript compiler (TSC).

Get TSC by installing TypeScript:

npm install --save-dev typescript
Copy the code

Add the tsconfig.json file to the root directory to configure TypeScript and TSC:

{
	"compilerOptions": {
		// Target latest version of ECMAScript.
		"target": "esnext".// Search under node_modules for non-relative imports.
		"moduleResolution": "node".// Process & infer types from .js files.
		"allowJs": true.// Don't emit; allow Babel to transform files.
		"noEmit": true.// Enable strictest settings like strictNullChecks & noImplicitAny.
		"strict": true.// Disallow features that require cross-file information for emit.
		"isolatedModules": true.// Import non-ES modules as default imports.
		"esModuleInterop": true
	},
	"include": [
		"src"]}Copy the code

complete

OK, the configuration is complete. Now run NPM run check-types (listening mode: NPM run check-types — –watch) to make sure the TypeScript code works. You may find some unknown but real bugs, which is not necessarily a bad thing, and this Javascript migration guide can help.

Microsoft’s typescript-Babel-starter includes additional setup instructions, including installing Babel from scratch, generating type definitions (D.ts) files, and using it with React.

What about code inspection tools?

usetslint

Updated in February 2019: Using ESLint! The TypeScript team has been focusing on ESLint integration since January. Configuring ESLint is much easier thanks to the @typescript-esLint project. For inspiration, check out my ultimate ESLint configuration, which includes TypeScript, Airbnb, Prettier, and React.

Babel + TypeScript = Beautiful marriage

Babel is the only JavaScript compiler needed, and it can be configured to handle anything.

There’s no need for two JavaScript compilers to compete, simplify project configuration, and take advantage of Babel’s integration with ESLint, unit tests, build systems, and project templates.

The combination of Babel and TypeScript compiles quickly and allows you to remain in a DND space while coding, and check types only when you’re ready.

Prediction: TypeScript will rise

According to the latest Stack Overflow developer survey, JavaScript is the most popular language, with TypeScript trailing in 12th place. This is still a great achievement for TypeScript, as it beats Ruby, Swift, and Go.

I predict TypeScript will be in the top 10 next year.

The TypeScript team is working hard to collaborate with other teams. This Babel Preset is a one year collaboration, and their new focus is improving ESLint integration. It’s a smart move — leveraging the capabilities, communities and plugins of existing tools. Developing compilers and code checkers to compete with others is a waste of energy.

Simply adjust the configuration of our favorite tools to lay out paths into TypeScript. Barriers to TypeScript entry have been removed.

With the popularity of VS Code, developers have set up a great TypeScript environment.

It is now also integrated into Create-React-App V2.0, bringing TypeScript to users at a rate of 200,000 downloads per month.

If you’re putting off getting into TypeScript because it’s hard to set up, it’s no longer an excuse. Now’s the time to give it a try.