Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build: Output package type declarations #18942

Merged
merged 65 commits into from
Mar 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
d1ec2b8
Add tsconfigs for packages
sirreal Feb 26, 2020
38814d0
Update TypeScript package
sirreal Feb 26, 2020
9c238dd
Add types
sirreal Feb 26, 2020
d6c5808
Gitignore types output
sirreal Feb 26, 2020
152ce84
Clean build-types
sirreal Feb 26, 2020
cd066a3
Add missing Parameters utility type
sirreal Feb 27, 2020
48cf167
Fix PriorityQueue types
sirreal Feb 27, 2020
d970cb3
Add sprintf-js types
sirreal Feb 27, 2020
62d2023
Type plural_forms function
sirreal Feb 27, 2020
8645170
Allow i18n implicit any for untyped dependencies
sirreal Feb 27, 2020
77c3835
Add include
sirreal Feb 27, 2020
fb52cee
Add tsbuildinfo locations
sirreal Feb 27, 2020
124a8b3
Clean the right directories
sirreal Feb 27, 2020
fcbff69
Remove root tsconfig
sirreal Feb 27, 2020
eb26707
Add build-types
sirreal Feb 27, 2020
bee32b5
Disable token-list types
sirreal Feb 27, 2020
af14a3e
Remove ts cache from cleanup
sirreal Feb 27, 2020
a10f1a5
Include build-types in files
sirreal Feb 27, 2020
d9141ec
Use "build" over "b"
sirreal Feb 27, 2020
9754612
Remove lint-types from lint
sirreal Feb 28, 2020
d6a20ea
Clean caches, some config cleanup
sirreal Mar 3, 2020
4cfe893
Remove redundant resolve
sirreal Mar 3, 2020
ba8e7c5
No async, no catch
sirreal Mar 5, 2020
214e1ff
Use default .tsbuildinfo location
sirreal Mar 5, 2020
1042f71
Clean up tsconfig
sirreal Mar 5, 2020
0cca987
"Fix" token-list
sirreal Mar 5, 2020
71b0dd8
Use eslint dis/enable no-console pair
sirreal Mar 5, 2020
1268c2f
Move types built to build:packages
sirreal Mar 5, 2020
80c0a02
Add TypeScript to packages/README
sirreal Mar 6, 2020
adbb0dd
Ignore cli input
sirreal Mar 6, 2020
973f5fb
Add build:package-types to lint-staged
sirreal Mar 6, 2020
09c9955
Add travis job
sirreal Mar 6, 2020
2e3bdce
Add and use lint-staged-typecheck bin
sirreal Mar 6, 2020
7c277f4
Update bin/packages/lint-staged-typecheck.js
sirreal Mar 6, 2020
d11fe6a
Restructure is-shallow-equal
sirreal Mar 7, 2020
384c78e
Bump to TS 3.8.3
sirreal Mar 11, 2020
36d4649
Type TokenList
sirreal Mar 11, 2020
7e71ee6
Add project-management-automation to typed packages
sirreal Mar 20, 2020
5ab371b
Use lib for uncompiled published code
sirreal Mar 20, 2020
8fc3c0e
Fix implicit any type
sirreal Mar 20, 2020
7dc9a43
Disable noImplicitAny for pma
sirreal Mar 20, 2020
94b9451
Exclude react-native
sirreal Mar 20, 2020
3230e83
Restore native checking, relax implicit any
sirreal Mar 20, 2020
47b24c3
Improve is-shallow-equal structure
sirreal Mar 21, 2020
448fd2f
Proposal: Use root ts project
sirreal Mar 22, 2020
ad9f5bc
Use double quotes in package scripts
sirreal Mar 25, 2020
7e9a6e1
Only clean types on publish
sirreal Mar 25, 2020
e2d8f86
Run lint-stage via npm script
sirreal Mar 25, 2020
9151cd1
Remove is-shallow-equal/{arrays,objects} support
sirreal Mar 25, 2020
70b1c2e
Proposal: Check all types on lint-staged
sirreal Mar 25, 2020
ad17ba1
Drop tsc verbose build
sirreal Mar 25, 2020
1251ec6
Fix types in token-list
sirreal Mar 25, 2020
8dffe92
Explain lint-staged script with a comment
sirreal Mar 26, 2020
0236148
Restore bin typechecking
sirreal Mar 26, 2020
89a0540
Comment cache outdir
sirreal Mar 26, 2020
9c5782c
Remove redundant entry from is-shallow-equal files
sirreal Mar 26, 2020
c4516f3
Disable declarationMap for bin
sirreal Mar 26, 2020
adb7a78
Add types to package.json lint
sirreal Mar 27, 2020
a213ca9
Update is-shallow-equal benchmarks
sirreal Mar 27, 2020
6ee66b5
Update is-shallow-equal tests
sirreal Mar 27, 2020
4d95dc0
Revert "Explain lint-staged script with a comment"
sirreal Mar 27, 2020
bc0eac3
Revert "Proposal: Check all types on lint-staged"
sirreal Mar 27, 2020
3fbe6f2
Revert "Run lint-stage via npm script"
sirreal Mar 27, 2020
a9c8577
Log type errors with lint-staged
sirreal Mar 27, 2020
dfd2bc1
Update changelog for affected packages
sirreal Mar 27, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
build
build-module
build-style
build-types
node_modules
gutenberg.zip

Expand All @@ -14,6 +15,7 @@ yarn.lock

playground/dist
.cache
*.tsbuildinfo

# Report generated from jest-junit
test/native/junit.xml
Expand Down
7 changes: 7 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ jobs:
script:
- npx eslint --parser-options=ecmaVersion:5 --no-eslintrc --no-ignore ./build/**/*.js

- name: Typecheck
install:
- npm ci
script:
- npm run build:package-types


- name: Build artifacts
install:
# A "full" install is executed, since `npm ci` does not always exit
Expand Down
34 changes: 34 additions & 0 deletions bin/packages/lint-staged-typecheck.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* External dependencies
*/
const _ = require( 'lodash' );
const path = require( 'path' );
const fs = require( 'fs' );
const execa = require( 'execa' );

/* eslint-disable no-console */

const repoRoot = path.join( __dirname, '..', '..' );
const tscPath = path.join( repoRoot, 'node_modules', '.bin', 'tsc' );

// lint-staged passes full paths to staged changes
const changedFiles = process.argv.slice( 2 );

// Transform changed files to package directories containing tsconfig.json
const changedPackages = _.uniq(
changedFiles.map( ( fullPath ) => {
const relativePath = path.relative( repoRoot, fullPath );
return path.join( ...relativePath.split( path.sep ).slice( 0, 2 ) );
} )
).filter( ( packageRoot ) =>
fs.existsSync( path.join( packageRoot, 'tsconfig.json' ) )
);

try {
execa.sync( tscPath, [ '--build', ...changedPackages ] );
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we keep this script lint-staged, this could invoke build:package-types script with -- ...changedPackages.

I'd prefer to remove this entirely as noted: https://github.com/WordPress/gutenberg/pull/18942/files#r396317889

} catch ( err ) {
console.error( err.stdout );
process.exitCode = 1;
}

/* eslint-enable no-console */
17 changes: 17 additions & 0 deletions bin/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "ES6",
"lib": [ "ES6", "ES2020.string" ],
"rootDir": ".",
"declarationMap": false,

// We're not interested in the output, but we must generate
// something as part of a composite project. Use the
// ignored `.cache` file to hide tsbuildinfo and d.ts files.
"outDir": ".cache"
},
"files": [ "./api-docs/update-api-docs.js" ]
}
24 changes: 21 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 14 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@
"@storybook/addon-viewport": "5.3.2",
"@storybook/react": "5.3.2",
"@types/jest": "24.0.25",
"@types/lodash": "4.14.149",
"@types/qs": "6.9.1",
"@types/requestidlecallback": "0.3.1",
"@types/sprintf-js": "1.1.2",
"@wordpress/babel-plugin-import-jsx-pragma": "file:packages/babel-plugin-import-jsx-pragma",
"@wordpress/babel-plugin-makepot": "file:packages/babel-plugin-makepot",
"@wordpress/babel-preset-default": "file:packages/babel-preset-default",
Expand Down Expand Up @@ -167,16 +170,18 @@
"sprintf-js": "1.1.1",
"style-loader": "1.0.0",
"stylelint-config-wordpress": "13.1.0",
"typescript": "3.5.3",
"typescript": "3.8.3",
"uuid": "3.3.2",
"webpack": "4.42.0",
"worker-farm": "1.7.0"
},
"scripts": {
"prebuild": "npm run check-engines",
"clean:packages": "rimraf ./packages/*/build ./packages/*/build-module ./packages/*/build-style ./packages/*/node_modules",
"clean:packages": "rimraf \"./packages/*/@(build|build-module|build-style)\"",
"clean:package-types": "tsc --build --clean",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn’t it be part of clean:packages that is executed as prebuild:packages?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's some conversation around this in the thread here: #18942 (comment)

In summary, there's enormous benefit to having a warm TypeScript cache and I don't believe there's any reason to clean it except to remove outdated declaration files from packages before they will be published.

In particular, we'll want to keep the caches warm for typechecking as part of lint staged.

"prebuild:packages": "npm run clean:packages && lerna run build",
"build:packages": "node ./bin/packages/build.js",
"build:packages": "npm run build:package-types && node ./bin/packages/build.js",
"build:package-types": "tsc --build",
"build": "npm run build:packages && wp-scripts build",
"check-engines": "wp-scripts check-engines",
"check-licenses": "concurrently \"wp-scripts check-licenses --prod --gpl2\" \"wp-scripts check-licenses --dev\"",
Expand All @@ -191,22 +196,21 @@
"fixtures:generate": "npm run fixtures:server-registered && cross-env GENERATE_MISSING_FIXTURES=y npm run test-unit",
"fixtures:regenerate": "npm run fixtures:clean && npm run fixtures:generate",
"format-js": "wp-scripts format-js",
"lint": "concurrently \"npm run lint-js\" \"npm run lint-pkg-json\" \"npm run lint-css\" \"npm run lint-types\"",
"lint": "concurrently \"npm run lint-js\" \"npm run lint-pkg-json\" \"npm run lint-css\"",
"lint-js": "wp-scripts lint-js",
"lint-js:fix": "npm run lint-js -- --fix",
"lint-php": "npm run wp-env run composer run-script lint",
"lint-pkg-json": "wp-scripts lint-pkg-json . 'packages/*/package.json'",
"lint-css": "wp-scripts lint-style '**/*.scss'",
"lint-css:fix": "npm run lint-css -- --fix",
"lint-types": "tsc",
sirreal marked this conversation as resolved.
Show resolved Hide resolved
"lint:md-js": "wp-scripts lint-md-js",
"lint:md-docs": "wp-scripts lint-md-docs",
"package-plugin": "./bin/build-plugin-zip.sh",
"pot-to-php": "./bin/pot-to-php.js",
"publish:check": "lerna updated",
"publish:dev": "npm run build:packages && lerna publish --dist-tag next",
"publish:legacy": "npm run build:packages && lerna publish --dist-tag legacy",
"publish:prod": "npm run build:packages && lerna publish",
"publish:dev": "npm run clean:package-types && npm run build:packages && lerna publish --dist-tag next",
"publish:legacy": "npm run clean:package-types && npm run build:packages && lerna publish --dist-tag legacy",
"publish:prod": "npm run clean:package-types && npm run build:packages && lerna publish",
"test": "npm run lint && npm run test-unit",
"test-e2e": "wp-scripts test-e2e --config packages/e2e-tests/jest.config.js",
"test-e2e:watch": "npm run test-e2e -- --watch",
Expand Down Expand Up @@ -252,7 +256,8 @@
],
"packages/**/*.js": [
"node ./bin/api-docs/update-api-docs.js",
"node ./bin/api-docs/are-api-docs-unstaged.js"
"node ./bin/api-docs/are-api-docs-unstaged.js",
"node ./bin/packages/lint-staged-typecheck.js"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

901ce5d removed the custom build script and relies on a root tsconfig.json that references each project. This simplifies the type build significantly.

I'm inclined to have the lint-staged execute npm run packages:build-types. That would remove an additional custom script introduced here.

Once the TypeScript cache is warm, incremental builds are quick or instant. Running the entire type build has the benefit of detecting when type incompatibilities across packages are introduced, while the current version only detects that the changed package itself typechecks and issues between packages would surface later on CI when the types are compiled.

@aduth Curious to hear your thoughts.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I attempted to do this and it's quite difficult because lint-staged always passes the changed files at the end, meaning we wind up with a command like the following:

npm run build:package-types "…/gutenberg/packages/a11y/src/index.js"

# tsc --build --verbose "…/gutenberg/packages/a11y/src/index.js"
# error TS6053: File '…/gutenberg/packages/a11y/src/index.js/tsconfig.json' not found.

If lint-staged is defined as a js file, lint-staged tasks can be declared as functions which makes it trivial to ignore the files input.

Are we open to that? I'd prefer to handle that in its own PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm inclined to have the lint-staged execute npm run packages:build-types. That would remove an additional custom script introduced here. [...] Once the TypeScript cache is warm, incremental builds are quick or instant.

Is the motivation to avoid maintaining the custom script, or because it may be faster to run a (warmed) full build than to typecheck individual package/files?

I'm motivated to keep these pre-commits fast. I'm not overly concerned with the maintenance burden of a custom script, if it means we can have faster/more granular checks.

Running the entire type build has the benefit of detecting when type incompatibilities across packages are introduced, while the current version only detects that the changed package itself typechecks and issues between packages would surface later on CI when the types are compiled.

I agree it would be good to have more immediate feedback about potential issues. If it can be fast enough to not become a burden, then I like the idea. I'd also be content if at least this is considered in the full Travis build.

Aside: Slow pre-commit has become a pet-peeve of mine lately (see #18840), in case that helps contextualize my thoughts in approaching this.

Copy link
Member Author

@sirreal sirreal Mar 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the motivation to avoid maintaining the custom script

This is a motivation, I prefer offloading as much as possible directly to tsc without indirection.

or because it may be faster to run a (warmed) full build than to typecheck individual package/files?

This is not a concern. A warm build of everything will likely be almost identical to a warm typecheck of changed files. Only the necessary things would be rebuilt.

The difference between a hot and cold cache is huge. The difference between a single package and all packages with a cold cache is also very large:

# Cold cache all
npm run clean:packages; time npm run build:package-types
# real    0m37.884s
# user    0m46.316s
# sys     0m1.311s

# Cold cache only URL (random package)
npm run clean:packages; time npm run build:package-types -- packages/url
# real    0m5.567s
# user    0m8.644s
# sys     0m0.353s

# Hot cache all
npm run build:package-types; time npm run build:package-types
# real    0m0.515s
# user    0m0.356s
# sys     0m0.091s

If a package has changed, it will be rebuilt. If it's dependencies have not been built, they will be built first. Given that rebuilding an unchanged package with a warm cache is practically free, the difference between building a single package and building all packages should be insignificant.

I agree these staged checks should be near immediate, and I don't feel too strongly about this.

We might try to persist TypeScript caches longer. TypeScript does an excellent job of doing absolutely nothing very quickly if it doesn't need to. I suspect it's only important to clean these types files before publish, so perhaps tsc --build --clean should be removed from build:packages and into the publish:… scripts and we could.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might try to persist TypeScript caches longer.

I've done this in 12302c0 where type cleaning is moved to publish scripts.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

51195f3 proposes typechecking all modules on lint-staged. Feel free to play with it, but if you feel strongly we can roll this back. I don't feel strongly one way or the other.

]
},
"wp-env": {
Expand Down
151 changes: 103 additions & 48 deletions packages/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,44 @@ This repository uses [lerna] to manage WordPress modules and publish them as pac
When creating a new package, you need to provide at least the following:

1. `package.json` based on the template:
```json
{
"name": "@wordpress/package-name",
"version": "1.0.0-beta.0",
"description": "Package description.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
"keywords": [
"wordpress"
],
"homepage": "https://github.com/WordPress/gutenberg/tree/master/packages/package-name/README.md",
"repository": {
"type": "git",
"url": "https://github.com/WordPress/gutenberg.git"
},
"bugs": {
"url": "https://github.com/WordPress/gutenberg/issues"
},
"main": "build/index.js",
"module": "build-module/index.js",
"react-native": "src/index",
"dependencies": {
"@babel/runtime": "^7.8.3"
},
"publishConfig": {
"access": "public"
}
}
```
This assumes that your code is located in the `src` folder and will be transpiled with `Babel`.
```json
{
"name": "@wordpress/package-name",
"version": "1.0.0-beta.0",
"description": "Package description.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
"keywords": [ "wordpress" ],
"homepage": "https://github.com/WordPress/gutenberg/tree/master/packages/package-name/README.md",
"repository": {
"type": "git",
"url": "https://github.com/WordPress/gutenberg.git"
},
"bugs": {
"url": "https://github.com/WordPress/gutenberg/issues"
},
"main": "build/index.js",
"module": "build-module/index.js",
"react-native": "src/index",
"dependencies": {
"@babel/runtime": "^7.8.3"
},
"publishConfig": {
"access": "public"
}
}
```
This assumes that your code is located in the `src` folder and will be transpiled with `Babel`.
2. `.npmrc` file which disables creating `package-lock.json` file for the package:
```
package-lock=false
```
```
package-lock=false
```
3. `README.md` file containing at least:
- Package name
- Package description
- Installation details
- Usage example
- `Code is Poetry` logo (`<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p>`)
- Package name
- Package description
- Installation details
- Usage example
- `Code is Poetry` logo (`<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p>`)

## Managing Dependencies

Expand All @@ -57,7 +55,7 @@ There are two types of dependencies that you might want to add to one of the exi
Production dependencies are stored in the `dependencies` section of the package’s `package.json` file.

#### Adding New Dependencies

The simplest way to add a production dependency to one of the packages is to run a very convenient [lerna add](https://github.com/lerna/lerna/tree/master/commands/add#readme) command from the root of the project.

_Example:_
Expand Down Expand Up @@ -91,9 +89,10 @@ Next, you need to run `npm install` in the root of the project to ensure that `p
#### Updating Existing Dependencies

This is the most confusing part of working with [lerna] which causes a lot of hassles for contributors. The most successful strategy so far is to do the following:
1. First, remove the existing dependency as described in the previous section.
2. Next, add the same dependency back as described in the first section of this chapter. This time it wil get the latest version applied unless you enforce a different version explicitly.


1. First, remove the existing dependency as described in the previous section.
2. Next, add the same dependency back as described in the first section of this chapter. This time it wil get the latest version applied unless you enforce a different version explicitly.

### Development Dependencies

In contrast to production dependencies, development dependencies shouldn't be stored in individual WordPress packages. Instead they should be installed in the project's `package.json` file using the usual `npm install` command. In effect, all development tools are configured to work with every package at the same time to ensure they share the same characteristics and integrate correctly with each other.
Expand All @@ -119,16 +118,16 @@ _Example:_

### Bug Fix

- Fixed an off-by-one error with the `sum` function.
- Fixed an off-by-one error with the `sum` function.
```

There are a number of common release subsections you can follow. Each is intended to align to a specific meaning in the context of the [Semantic Versioning (`semver`) specification](https://semver.org/) the project adheres to. It is important that you describe your changes accurately, since this is used in the packages release process to help determine the version of the next release.

- "Breaking Change" - A backwards-incompatible change which requires specific attention of the impacted developers to reconcile (requires a major version bump).
- "New Feature" - The addition of a new backwards-compatible function or feature to the existing public API (requires a minor verison bump).
- "Enhancement" - Backwards-compatible improvements to existing functionality (requires a minor version bump).
- "Bug Fix" - Resolutions to existing buggy behavior (requires a patch version bump).
- "Internal" - Changes which do not have an impact on the public interface or behavior of the module (requires a patch version bump).
- "Breaking Change" - A backwards-incompatible change which requires specific attention of the impacted developers to reconcile (requires a major version bump).
- "New Feature" - The addition of a new backwards-compatible function or feature to the existing public API (requires a minor verison bump).
- "Enhancement" - Backwards-compatible improvements to existing functionality (requires a minor version bump).
- "Bug Fix" - Resolutions to existing buggy behavior (requires a patch version bump).
- "Internal" - Changes which do not have an impact on the public interface or behavior of the module (requires a patch version bump).

While other section naming can be used when appropriate, it's important that are expressed clearly to avoid confusion for both the packages releaser and third-party consumers.

Expand Down Expand Up @@ -190,5 +189,61 @@ npm run publish:legacy

This is usually necessary when adding bug fixes or security patches to the earlier versions of WordPress.

## TypeScript

The [TypeScript](http://www.typescriptlang.org/) language is a typed superset of JavaScript that compiles to plain JavaScript.
Gutenberg does not use the TypeScript language, however TypeScript has powerful tooling that can be applied to JavaScript projects.

Gutenberg uses TypeScript for several reasons, including:

- Powerful editor integrations improve developer experience.
- Type system can detect some issues and lead to more robust software.
- Type declarations can be produced to allow other projects to benefit from these advantages as well.

### Using TypeScript

Gutenberg uses TypeScript by running the TypeScript compiler (`tsc`) on select packages.
These packages benefit from type checking and produced type declarations in the published packages.

To opt-in to TypeScript tooling, packages should include a `tsconfig.json` file in the package root and add an entry to the root `tsconfig.json` references.
The changes will indicate that the package has opted-in and will be included in the TypeScript build process.

A `tsconfig.json` file should look like the following (comments are not necessary):

```jsonc
{
// Extends a base configuration common to most packages
"extends": "../../tsconfig.base.json",

// Options for the TypeScript compiler
// We'll usually set our `rootDir` and `declarationDir` as follows, which is specific
// to each project.
"compilerOptions": {
"rootDir": "src",
"declarationDir": "build-types"
},

// Which source files should be included
"include": [ "src/**/*" ],

// Other WordPress package dependencies that have opted-in to TypeScript should be listed
// here. In this case, our package depends on `@wordpress/dom-ready`.
"references": [ { "path": "../dom-ready" } ]
}
```

Type declarations will be produced in the `build-types` which should be included in the published package.
For consumers to use the published type declarations, we'll set the `types` field in `package.json`:

```json
{
"main": "build/index.js",
"main-module": "build-module/index.js",
"types": "build-types"
}
```

Ensure that the `build-types` directory will be included in the published package, for example if a `files` field is declared.

[lerna]: https://lerna.js.org/
[npm]: https://www.npmjs.com/