Description
This issue is meant to track Jest's internal migration to TypeScript.
Process
We would love to get help from the community here. I've compiled a list of all the packages in this repo below - feel free to claim any package not claimed and submit a PR migrating it.
List
Package Name | Task Owner | PR | Status | Notes |
---|---|---|---|---|
@jest/core |
@SimenB | #7998 | MERGED | |
@jest/reporters |
@loryman | #7994 | MERGED | |
@jest/transform |
@SimenB | #7918 | MERGED | |
babel-jest |
@SimenB | #7862 | MERGED | |
babel-plugin-jest-hoist |
@deneuv34 | #7898 | MERGED | |
babel-preset-jest |
- | - | - | Not transpiled |
diff-sequences |
@loryman | #7820 | MERGED | |
eslint-config-fb-strict |
- | - | - | Not transpiled |
expect |
@natealcedo | #7919 | MERGED | |
jest |
@SimenB | #8024 | MERGED | |
jest-changed-files |
@loryman | #7827 | MERGED | |
jest-circus |
@doniyor2109 | #7916 | MERGED | |
jest-cli |
@SimenB | #8024 | MERGED | |
jest-config |
@SimenB | #7944 | MERGED | |
jest-diff |
@SimenB | #7824 | MERGED | |
jest-docblock |
@SimenB | #7836 | MERGED | |
jest-each |
@mattphillips | #8007 | MERGED | |
jest-environment-jsdom |
@lirbank | #8003 | MERGED | |
jest-environment-node |
@lirbank | #7985 | MERGED | |
jest-get-type |
@SimenB | #7818 | MERGED | |
jest-haste-map |
@jeysal | #7854 | MERGED | |
jest-jasmine2 |
@doniyor2109 | #7970 | MERGED | |
jest-leak-detector |
@r3nya | #7825 | MERGED | |
jest-matcher-utils |
@SimenB | #7835 | MERGED | |
jest-message-util |
@SimenB | #7834 | MERGED | |
jest-mock |
@thymikee | #7847 | MERGED | |
jest-phabricator |
@r3nya | #7965 | MERGED | |
jest-regex-util |
@loryman | #7822 | MERGED | |
jest-repl |
@natealcedo | #8000 | MERGED | |
jest-resolve |
@SimenB | #7871 | MERGED | |
jest-resolve-dependencies |
@jeysal | #7922 | MERGED | |
jest-runner |
@natealcedo | #7968 | MERGED | |
jest-runtime |
@SimenB | #7964 | MERGED | |
jest-serializer |
@thymikee | #7841 | MERGED | |
jest-snapshot |
@doniyor2109 | #7899 | MERGED | |
jest-util |
@SimenB | #7844 | MERGED | |
jest-validate |
@SimenB | #7991 | MERGED | |
jest-watcher |
@SimenB | #7843 | MERGED | |
jest-worker |
@SimenB | #7853 | MERGED | |
pretty-format |
@SimenB | #7809 | MERGED |
After all packages are migrated, we can start to migrate our integration tests. Depending on how this migration goes, we can track that in this issue as well, or we can track it separately later.
How
Order of packages to migrate
One thing to note is that because this repo is a monorepo, we have dependencies between packages. So we have to migrate leaf packages (without dependencies) first, then walk up the dependency tree until everything is migrated. Which means jest-cli
will be the last package migrated.
You can use yarn to figure out which packages depend on which internally: yarn --silent workspaces info
. This will output a JSON object of all packages in the workspace. An example looks like this:
{
"babel-jest": {
"location": "packages/babel-jest",
"workspaceDependencies": ["babel-preset-jest"],
"mismatchedWorkspaceDependencies": []
}
}
The interesting part here is workspaceDependencies
. If that array is empty, that's a perfect package to start migrating. If it is not empty, you'll want to make sure that every package listed in the array has been migrated already.
Steps
- Claim a package in this issue
- Copy
tsconfig.json
from an already migrated package- If the package you're migrating have dependencies on another package in this repo, use
references
- If the package you're migrating have dependencies on another package in this repo, use
- If a type file exists in
types/
in the root of the repo for the package, move that into the package'ssrc
directory as a file namedtypes.ts
- Add
"types": "build/index.d.ts"
to package.json belowmain
- Rename all files with
js
extension tots
(ortsx
if they have jsx in them), fixing type errors as you go - Make sure tests and lint (including flow) pass
- Ensure that the JS after compilation is essentially the same as before migrating*
- Open up a PR
To build, you can run yarn build
or yarn watch
in the root of the repository.
You can look at my PR for pretty-format
for a look at how a migration might look.
You can use flow-to-typescript
to help in migration. However, since the syntax between Flow and Typescript is so similar, I personally only used it for the type definition files in types
- for normal source files it was easier to rename the file to ts(x)
and fix the syntax errors that my IDE showed me.
*) Do this by comparing git diff
s before and after migration (also please include this diff in the PR after opening it)
- run
yarn build
onmaster
git add -f packages/MY_PACKAGE/build*
git commit -m 'before migration'
- run
yarn build
on your branch with the migration rm packages/MY_PACKAGE/build*/**/*.ts packages/MY_PACKAGE/build*/**/*.map
git add -f packages/MY_PACKAGE/build*
git commit -m 'after migration'
git diff master packages/MY_PACKAGE/build*
- On macOS (there probably exists similar tools on Linux and Windows), this can be copied and included in the PR
git --no-pager diff master packages/MY_PACKAGE/build* | pbcopy
. Stick that in a code fence withdiff
syntax in the PR.
Things to look out for during migration
The config doesn't allow implicit any
Out current setup with flow allows this - just add an explicit any
(or a stricter type if you're able) in those cases. If possible, please use unknown
instead of any
.
The module exports CommonJS
Convert require
to import
Use exports =
to replace modules.exports
- this allows TypeScript to understand the export. We include a babel-plugin which transpiles this into module.exports
for the distributed code (and tests).
Potential gotchas
Probably more, but I'll write down the ones I know of
- Jest currently imports quite a lot of types from
types/
in the root of this repo, allowing us to use types across packages without dependencies on them (typically modules will depend ontypes/Config
which allow them to haveProjectConfig
as arguments). Since we'll be distributing the types, we need those dependencies to be explicit.- A solution in this concrete case is probably to create a separate packages that has everything
jest-config
has today except for the default configs (so it can dropbabel-jest
, the test environments etc)
- A solution in this concrete case is probably to create a separate packages that has everything
- Similarly,
types/TestResult
is used byjest-jasmine2
,jest-circus
andjest-cli
(for reporters). We need to figure out how to share that type effectively between packages.
Another idea on how to solve "type sharing" is to use a separate jest-types
project that's just types that are shared between modules.
Ideas here are very much welcome!
EDIT: As of #7834, I've created a @jest/types
package
PS: This will not affect anyone using Jest (unless you use the modules exported by Jest directly, which will become typed). This is strictly an internal refactor. We will not be considering adding types to be a breaking change.
PPS: It is currently a non-goal to distribute TS types for using Jest - that is excellently handled in @types/jest
already. At some point we might want to distribute that with jest as well - but that's a separate issue.
PPPS: This issue is not for discussions about the merits of the migration in and of itself - that feedback can be posted in the RFC. However, if you have experience migrating, building, testing or distributing a module written in TS, feel free to chime in with learnings from that process in this issue.