Skip to content

Conversation

@mcmire
Copy link
Contributor

@mcmire mcmire commented Mar 18, 2022

Currently, we exclude test files from TypeScript's purview, so that only
files in src/ get emitted to dist/. This makes sense from a release
perspective, but it interferes with development.

One example of this interference involves ambient modules. We have
a file dependencies.d.ts which we can use to backfill missing types
for various dependencies. The problem is that while TypeScript (or, more
accurately, tsserver) can see the types specified here when reading
source files, it doesn't seem to pick them up for test files. This
causes in-editor inconsistencies with type analysis and, in some cases,
warnings such as:

  • import can only be used with esInteropModuleFlag: true
  • X is missing type definitions

The reason this is happening is that type definition files are not
intended to just be placed in the source directory. You can either use
triple-slash directives to bring them in, or you can modify a setting in
tsconfig.json (paths) that will instruct TypeScript where it should
find types for modules that are imported
. This commit chooses the
latter option. Note that this requires we split up dependencies.d.ts
into separate type definition files, one per module.

In addition to modifying tsconfig.json, this commit also breaks up
this config file into a global/development version and a version that is
specific to the build/release process. This allows editors to use
the same exact TypeScript settings for test files as for non-test files.
tsconfig.build.json is used by yarn build and will limit the files
emitted to dist/ to only non-test files in src/, as in the original
configuration.


Manual testing steps

  • Check out the main branch.
  • Open src/assets/AssetsContractController.test.ts.
  • Hover over MAINNET_PROVIDER on line 6. Note how the type is any. This is because the types for ethjs-provider-http is being stubbed in src/dependencies.d.ts.
  • Update the declare module 'ethjs-provider-http'; line in src/dependencies.d.ts to read:
    declare module 'ethjs-provider-http' {
      import type { JsonRpcRequest } from 'json-rpc-engine';
      export type EthQueryMethodCallback<R> = (error: any, response: R) => void;
    
      export default class HttpProvider {
        host: string;
        timeout: number;
    
        constructor(host: string, timeout?: number);
    
        sendAsync<P, R>(
          request: JsonRpcRequest<P>,
          callback: EthQueryMethodCallback<R>,
        ): void;
      }
    }
    
  • Hover over MAINNET_PROVIDER in src/assets/AssetsContractController.test.ts again. Note how the type is still any.
  • Remove your changes to src/dependencies.d.ts.
  • Now check out this branch.
  • Restore your changes to src/dependencies.d.ts.
  • Hover over MAINNET_PROVIDER in src/assets/AssetsContractController.test.ts a third time. Note how the type is properly HttpProvider.
  • Finally, run yarn build. All of the files we would expect to show up in dist/ should be there (i.e. no extra .d.ts files, no tests, etc.)

@mcmire mcmire requested a review from a team as a code owner March 18, 2022 22:55
@mcmire mcmire changed the title Create tests-only TypeScript configuration Extract build-only TypeScript configuration Mar 18, 2022
@mcmire mcmire force-pushed the fix-tsconfig-for-tests branch 3 times, most recently from 75afffa to e3a972e Compare March 18, 2022 23:13
@Gudahtt
Copy link
Member

Gudahtt commented Mar 24, 2022

Huh. I hadn't considered this before. We should make this update in our template repo as well.

Gudahtt
Gudahtt previously approved these changes Mar 24, 2022
Copy link
Member

@Gudahtt Gudahtt left a comment

Choose a reason for hiding this comment

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

LGTM! I can't believe I hadn't noticed this before. Great PR description too, those repro steps were greatly appreciated

Gudahtt
Gudahtt previously approved these changes Mar 24, 2022
Currently, we exclude test files from TypeScript's purview, so that only
files in `src/` get emitted to `dist/`. This makes sense from a release
perspective, but it interferes with development.

One example of this interference involves [ambient modules][1]. We have
a file `dependencies.d.ts` which we can use to backfill missing types
for various dependencies. The problem is that while TypeScript (or, more
accurately, `tsserver`) can see the types specified here when reading
source files, it doesn't seem to pick them up for test files. This
causes in-editor inconsistencies with type analysis and, in some cases,
warnings such as:

* `import` can only be used with `esInteropModuleFlag: true`
* `X` is missing type definitions

The reason this is happening is that type definition files are not
intended to just be placed in the source directory. You can either use
triple-slash directives to bring them in, or you can modify a setting in
`tsconfig.json` (`paths`) that will [instruct TypeScript where it should
find types for modules that are imported][1]. This commit chooses the
latter option. Note that this requires we split up `dependencies.d.ts`
into separate type definition files, one per module.

In addition to modifying `tsconfig.json`, this commit also breaks up
this config file into a global/development version and a version that is
specific to the build/release process. This allows editors to use
the same exact TypeScript settings for test files as for non-test files.
`tsconfig.build.json` is used by `yarn build` and will limit the files
emitted to `dist/` to only non-test files in `src/`, as in the original
configuration.

[1]: https://www.typescriptlang.org/docs/handbook/modules.html#ambient-modules
[2]: https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping
@mcmire mcmire force-pushed the fix-tsconfig-for-tests branch from d130fde to ecd3eea Compare March 25, 2022 19:56
@mcmire mcmire changed the title Extract build-only TypeScript configuration Improve support for backfilling types via .d.ts's Mar 25, 2022
@mcmire
Copy link
Contributor Author

mcmire commented Mar 25, 2022

Okay, I've created a similar PR in the template repo here: MetaMask/metamask-module-template#95. As I was doing this, I learned a few more things about type definition files, and updated this PR to match those findings. I've left some more commentary on that particular PR than here, so that might be informative if you're not sure why dependencies.d.ts got split up. One more review please 🙏🏻

Copy link
Member

@Gudahtt Gudahtt left a comment

Choose a reason for hiding this comment

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

LGTM!

@mcmire mcmire merged commit 6f3808b into main Mar 30, 2022
@mcmire mcmire deleted the fix-tsconfig-for-tests branch March 30, 2022 20:06
rickycodes added a commit that referenced this pull request Apr 7, 2022
…o add-npm-publish

* 'add-npm-publish' of github.com:MetaMask/controllers:
  Improve support for backfilling types via .d.ts's (#732)
  Copy .gitattributes from template repo (#760)
  27.1.1 (#759)
  Move new keystone package to dependencies (#757)
MajorLift pushed a commit that referenced this pull request Oct 11, 2023
Currently, we exclude test files from TypeScript's purview, so that only
files in `src/` get emitted to `dist/`. This makes sense from a release
perspective, but it interferes with development.

One example of this interference involves [ambient modules][1]. We have
a file `dependencies.d.ts` which we can use to backfill missing types
for various dependencies. The problem is that while TypeScript (or, more
accurately, `tsserver`) can see the types specified here when reading
source files, it doesn't seem to pick them up for test files. This
causes in-editor inconsistencies with type analysis and, in some cases,
warnings such as:

* `import` can only be used with `esInteropModuleFlag: true`
* `X` is missing type definitions

The reason this is happening is that type definition files are not
intended to just be placed in the source directory. You can either use
triple-slash directives to bring them in, or you can modify a setting in
`tsconfig.json` (`paths`) that will [instruct TypeScript where it should
find types for modules that are imported][1]. This commit chooses the
latter option. Note that this requires we split up `dependencies.d.ts`
into separate type definition files, one per module.

In addition to modifying `tsconfig.json`, this commit also breaks up
this config file into a global/development version and a version that is
specific to the build/release process. This allows editors to use
the same exact TypeScript settings for test files as for non-test files.
`tsconfig.build.json` is used by `yarn build` and will limit the files
emitted to `dist/` to only non-test files in `src/`, as in the original
configuration.

[1]: https://www.typescriptlang.org/docs/handbook/modules.html#ambient-modules
[2]: https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping
MajorLift pushed a commit that referenced this pull request Oct 11, 2023
Currently, we exclude test files from TypeScript's purview, so that only
files in `src/` get emitted to `dist/`. This makes sense from a release
perspective, but it interferes with development.

One example of this interference involves [ambient modules][1]. We have
a file `dependencies.d.ts` which we can use to backfill missing types
for various dependencies. The problem is that while TypeScript (or, more
accurately, `tsserver`) can see the types specified here when reading
source files, it doesn't seem to pick them up for test files. This
causes in-editor inconsistencies with type analysis and, in some cases,
warnings such as:

* `import` can only be used with `esInteropModuleFlag: true`
* `X` is missing type definitions

The reason this is happening is that type definition files are not
intended to just be placed in the source directory. You can either use
triple-slash directives to bring them in, or you can modify a setting in
`tsconfig.json` (`paths`) that will [instruct TypeScript where it should
find types for modules that are imported][1]. This commit chooses the
latter option. Note that this requires we split up `dependencies.d.ts`
into separate type definition files, one per module.

In addition to modifying `tsconfig.json`, this commit also breaks up
this config file into a global/development version and a version that is
specific to the build/release process. This allows editors to use
the same exact TypeScript settings for test files as for non-test files.
`tsconfig.build.json` is used by `yarn build` and will limit the files
emitted to `dist/` to only non-test files in `src/`, as in the original
configuration.

[1]: https://www.typescriptlang.org/docs/handbook/modules.html#ambient-modules
[2]: https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants