TypeScript 4.5 Shortens Path to Safer Standard Library
Tags: typescript
Published: 2021-10-02 02:08:39

Amongst the new features of [TypeScript 4.5](https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/), support for [loading external packages in place of built-in type definitions (standard library)](https://github.com/microsoft/TypeScript/pull/45771) is particularly of note. The original intent seems to be externalizing `lib.dom.d.ts` as [@types/web](https://github.com/microsoft/TypeScript/issues/44795) so that users can have separate upgrading schedule for TypeScript's core type definitions and one for DOM. The type definitions for DOM are fragile and often breaks backwards compatibility, probably because they are auto-generated.

Thanks to this nicely generalized solution for externalized standard library, [better-typescript-lib](https://github.com/uhyo/better-typescript-lib), a library developed by the author, also receives huge benefit. Particularly, installation is far easier starting from better-typescript-lib v2 that supports TS 4.5 and later.

## What is better-typescript-lib?

[better-typescript-lib](https://github.com/uhyo/better-typescript-lib) is a package that provides alternative type definitions for standard library.

TypeScript's built-in type definitions are sometimes problematic in view of safety. For example, the return type of `JSON.parse` is any 😱 and it is too easy to guide users to the unsafe hell.

As TypeScript needs to keep backwards compatibility, directly fixing built-in type definitions is impossible. Previous solutions for this kind of problems have been compiler options, but something like `--strictStandardLibrary` does not look like a right way to go.

better-typescript-lib solves the problem by replacing the entire built-in type definitions with safer ones. It ships with alternative complete set of type definitions for supported ECMAScript and DOM features.

## Previous Installation Steps of better-typescript-lib

Before TS 4.5, installation of better-typescript-lib was a complicated task. Three steps were required:

1​. Install `better-typescript-lib`.
```sh
npm i -D better-typescript-lib
```

2​. Add `"noLib": true` to tsconfig.json so that TypeScript's built-in type definitions are not automatically loaded.

```diff
-  "lib": ["es5", "dom"]
+  "noLib": true
```

3​. Manually load needed libs from inside better-typescript-lib.

```ts
/// <reference path="./node_modules/better-typescript-lib/lib.es5.d.ts" />
/// <reference path="./node_modules/better-typescript-lib/lib.dom.d.ts" />
```

## New Installation Step

Thanks to TS 4.5's new feature, now you can use the safer type definitions by literally one step:

1​. Install `better-typescript-lib`.

```sh
npm i -D better-typescript-lib
```

Done! Wow, everything is so automatic. Now TypeScript loads safer type definitions instead of built-in ones.

## How the New Installation Step Works

Starting from TS 4.5, TypeScript detects packages of name with form `@typescript/lib-[lib]` and loads that package in place of corresponding built-in type definition. For example, `@typescript/lib-es2015` replaces built-in `lib.es2015.d.ts`. What a simple but widely applicable solution!

The `@typescript` scope is owned by TypeScript team, of course, but package managers support installing packages with different names. better-typescript-lib utilizes this feature and have below dependency definitions in package.json:

```json
    "@typescript/lib-dom": "npm:@better-typescript-lib/dom@2.0.0-alpha.1",
    "@typescript/lib-es2015": "npm:@better-typescript-lib/es2015@2.0.0-alpha.1",
    "@typescript/lib-es2016": "npm:@better-typescript-lib/es2016@2.0.0-alpha.1",
    "@typescript/lib-es2017": "npm:@better-typescript-lib/es2017@2.0.0-alpha.1",
    "@typescript/lib-es2018": "npm:@better-typescript-lib/es2018@2.0.0-alpha.1",
    "@typescript/lib-es2019": "npm:@better-typescript-lib/es2019@2.0.0-alpha.1",
    "@typescript/lib-es2020": "npm:@better-typescript-lib/es2020@2.0.0-alpha.1",
    "@typescript/lib-es2021": "npm:@better-typescript-lib/es2021@2.0.0-alpha.1",
    "@typescript/lib-es5": "npm:@better-typescript-lib/es5@2.0.0-alpha.1",
    "@typescript/lib-esnext": "npm:@better-typescript-lib/esnext@2.0.0-alpha.1",
    "@typescript/lib-header": "npm:@better-typescript-lib/header@2.0.0-alpha.1",
    "@typescript/lib-scripthost": "npm:@better-typescript-lib/scripthost@2.0.0-alpha.1",
    "@typescript/lib-webworker": "npm:@better-typescript-lib/webworker@2.0.0-alpha.1"
```

This way, safer type definitions published as `@better-typescript-lib/[lib]` are installed with names `@typescript/lib-[lib]` so that they are used instead of built-in type definitions.

_Note: this depends on the behavior of package managers that flattens contents in `node_modules`. Package managers with different strategy for dependency management may not work well. Support for such environments may be added in the future if there are several requests._

## Conclusion

TypeScript 4.5's new feature for replacing built-in type definitions shall have wide application. better-typescript-lib is one of the earliest users of the new feature and is now able to provide safety with far easier installation step.

You can try now by installing TypeScript 4.5 Beta and `better-typescript-lib@2.0.0-beta`.