Skip to content

Commit

Permalink
Implement selective typecheck (#2321)
Browse files Browse the repository at this point in the history
* Implement selective options for typecheck, apply selective logic to includes

* Segregate modularRoot util for tests

* Further tidy up of new command testing approach

* Add fixture and new test cases for selective typecheck

* Add changeset

* Cover allowlisted properties, fix path bug in util
  • Loading branch information
sgb-io authored Mar 28, 2023
1 parent 561d780 commit 962b5e5
Show file tree
Hide file tree
Showing 16 changed files with 618 additions and 102 deletions.
5 changes: 5 additions & 0 deletions .changeset/tiny-parents-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'modular-scripts': minor
---

Add selective options to typecheck
60 changes: 60 additions & 0 deletions __fixtures__/selective-typecheck-example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"name": "selective-typecheck-example",
"version": "1.0.0",
"main": "index.js",
"author": "Sam Brown <sam.brown@jpmorgan.com>",
"license": "MIT",
"private": true,
"workspaces": [
"packages/**"
],
"modular": {
"type": "root"
},
"scripts": {
"start": "modular start",
"build": "modular build",
"test": "modular test",
"lint": "eslint . --ext .js,.ts,.tsx",
"prettier": "prettier --write ."
},
"eslintConfig": {
"extends": "modular-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"prettier": {
"singleQuote": true,
"trailingComma": "all",
"printWidth": 80,
"proseWrap": "always"
},
"dependencies": {
"@testing-library/dom": "^8.20.0",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"@types/jest": "^29.4.0",
"@types/node": "^18.14.6",
"@types/react": "^18.0.9",
"@types/react-dom": "^18.0.8",
"eslint-config-modular-app": "^4.0.0",
"modular-scripts": "^4.1.0",
"modular-template-app": "^1.2.0",
"modular-template-source": "^1.1.0",
"prettier": "^2.8.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"typescript": "^4.8.3"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "selective-typecheck-common-module",
"private": false,
"modular": {
"type": "source"
},
"main": "./src/index.ts",
"types": "./src/index.ts",
"version": "1.0.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* eslint-disable */

// The following TS nocheck flag gets removed in test
// @ts-nocheck

export default function add(a: number, b: number): number {
return a + b + 'c';
}

export function otherThing(input) {
return typeof input;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
useModularEsbuild: true,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "app",
"private": true,
"modular": {
"type": "app"
},
"version": "1.0.0",
"dependencies": {
"selective-typecheck-common-module": "*"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React, { useEffect } from 'react';
import './App.css';

function App(): JSX.Element {
return (
<div className="App">
<header className="App-header">
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}

export default App;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "webpack-app",
"private": true,
"modular": {
"type": "app"
},
"version": "1.0.0",
"dependencies": {
"selective-typecheck-common-module": "*"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as React from 'react';
import './App.css';

function App(): JSX.Element {
return (
<div className="App">
<header className="App-header">
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}

export default App;
54 changes: 52 additions & 2 deletions docs/commands/typecheck.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,66 @@ parent: Commands
title: modular typecheck
---

# `modular typecheck [options]`
# `modular typecheck [options] [packages...]`

`modular typecheck` will programmatically report the semantic, syntactic, and
declaration type errors found in your code, based on your tsconfig.json.
declaration type errors found in your code, based on your `tsconfig.json`.

In a CI environment, it will print condensed errors if they are present.

In non-CI environments, it will print the full details of the error, line, and
small snapshot of the offending line in question.

## Configuration

`modular typecheck` will respect the root `tsconfig.json`, but most
`compilerOptions` are ignored.

It should be noted that `modular typecheck` does not support package-level
`tsconfig.json` files, for backwards compatibility. Your IDE may still consume
these, but it is recommended to keep your TypeScript configuration in the root
`tsconfig.json`.

_Why does Modular restrict compilerOptions?_

`modular typecheck` aims to verify that the project's types are passing without
errors. Certain TypeScript features such as emitting output are not useful in
this scenario, so Modular has always applied a restricted set of
`compilerOptions`.

Although this approach has limited flexibility, it fits with Modular's goals and
brings certain advantages:

- Configuration is kept minimal and simple where possible
- The possibility of incompatible or conflicting `compilerOptions` between
packages is avoided
- It enables the use of selective `modular typecheck` (i.e. supply package names
and using flags such as `--ancestors`)

There are certain exceptions for practical use cases. The current allowlist is:

- [jsx](https://www.typescriptlang.org/tsconfig#jsx)

Some use cases may warrant new exceptions. If this is you, please file an issue
with the project for consideration.

## Options:

`--verbose`: Enables verbose logging within modular

`--descendants`: Typecheck the packages specified by the `[packages...]`
argument and/or the `--changed` option and additionally typecheck all their
descendants (i.e. the packages they directly or indirectly depend on).

`--ancestors`: Typecheck the packages specified by the `[packages...]` argument
and/or the `--changed` option and additionally typecheck all their ancestors
(i.e. the packages that have a direct or indirect dependency on them).

`--changed`: Typecheck only the packages whose workspaces contain files that
have changed. Files that have changed are calculated comparing the current state
of the repository with the branch specified by `compareBranch` or, if
`compareBranch` is not set, with the default git branch.

`--compareBranch`: Specify the comparison branch used to determine which files
have changed when using the `changed` option. If this option is used without
`changed`, the command will fail.
Loading

0 comments on commit 962b5e5

Please sign in to comment.