├── .babelrc ├── .circleci └── config.yml ├── .eslintrc ├── .gitignore ├── .prettierrc ├── CHANGELOG.md ├── README.md ├── babel.config.js ├── docs └── assets │ └── preview.png ├── package.json ├── src ├── cli.ts ├── lib │ ├── git.ts │ └── typescript.ts └── ts-strictify.ts ├── tests ├── help │ └── help-output-mother.ts ├── repository │ ├── src │ │ ├── noImplicitAny.ts │ │ └── strictNullChecks.ts │ └── tsconfig.json ├── supported-options.spec.ts └── ts-strictify.spec.ts ├── tsconfig.json └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "node": "current" 8 | } 9 | } 10 | ], 11 | "@babel/preset-typescript" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/node:12.15.0 6 | steps: 7 | - checkout 8 | - run: 9 | name: install 10 | command: yarn install 11 | - run: 12 | name: build 13 | command: yarn build 14 | - run: 15 | name: test 16 | command: yarn test 17 | - run: 18 | name: release 19 | command: yarn release 20 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "extends": [ 4 | "plugin:@typescript-eslint/recommended", 5 | "prettier/@typescript-eslint", 6 | "plugin:prettier/recommended" 7 | ], 8 | "rules": { 9 | "@typescript-eslint/camelcase": "off", 10 | "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/node,macos,visualstudiocode 3 | # Edit at https://www.gitignore.io/?templates=node,macos,visualstudiocode 4 | 5 | ### macOS ### 6 | # General 7 | .DS_Store 8 | .AppleDouble 9 | .LSOverride 10 | 11 | # Icon must end with two \r 12 | Icon 13 | 14 | # Thumbnails 15 | ._* 16 | 17 | # Files that might appear in the root of a volume 18 | .DocumentRevisions-V100 19 | .fseventsd 20 | .Spotlight-V100 21 | .TemporaryItems 22 | .Trashes 23 | .VolumeIcon.icns 24 | .com.apple.timemachine.donotpresent 25 | 26 | # Directories potentially created on remote AFP share 27 | .AppleDB 28 | .AppleDesktop 29 | Network Trash Folder 30 | Temporary Items 31 | .apdisk 32 | 33 | ### Node ### 34 | # Logs 35 | logs 36 | *.log 37 | npm-debug.log* 38 | yarn-debug.log* 39 | yarn-error.log* 40 | lerna-debug.log* 41 | 42 | # Diagnostic reports (https://nodejs.org/api/report.html) 43 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 44 | 45 | # Runtime data 46 | pids 47 | *.pid 48 | *.seed 49 | *.pid.lock 50 | 51 | # Directory for instrumented libs generated by jscoverage/JSCover 52 | lib-cov 53 | 54 | # Coverage directory used by tools like istanbul 55 | coverage 56 | *.lcov 57 | 58 | # nyc test coverage 59 | .nyc_output 60 | 61 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 62 | .grunt 63 | 64 | # Bower dependency directory (https://bower.io/) 65 | bower_components 66 | 67 | # node-waf configuration 68 | .lock-wscript 69 | 70 | # Compiled binary addons (https://nodejs.org/api/addons.html) 71 | build/Release 72 | 73 | # Dependency directories 74 | node_modules/ 75 | jspm_packages/ 76 | 77 | # TypeScript v1 declaration files 78 | typings/ 79 | 80 | # TypeScript cache 81 | *.tsbuildinfo 82 | 83 | # Optional npm cache directory 84 | .npm 85 | 86 | # Optional eslint cache 87 | .eslintcache 88 | 89 | # Optional REPL history 90 | .node_repl_history 91 | 92 | # Output of 'npm pack' 93 | *.tgz 94 | 95 | # Yarn Integrity file 96 | .yarn-integrity 97 | 98 | # dotenv environment variables file 99 | .env 100 | .env.test 101 | 102 | # parcel-bundler cache (https://parceljs.org/) 103 | .cache 104 | 105 | # next.js build output 106 | .next 107 | 108 | # nuxt.js build output 109 | .nuxt 110 | 111 | # react / gatsby 112 | public/ 113 | 114 | # vuepress build output 115 | .vuepress/dist 116 | 117 | # Serverless directories 118 | .serverless/ 119 | 120 | # FuseBox cache 121 | .fusebox/ 122 | 123 | # DynamoDB Local files 124 | .dynamodb/ 125 | 126 | ### VisualStudioCode ### 127 | .vscode/* 128 | !.vscode/settings.json 129 | !.vscode/tasks.json 130 | !.vscode/launch.json 131 | !.vscode/extensions.json 132 | 133 | ### VisualStudioCode Patch ### 134 | # Ignore all local history of files 135 | .history 136 | 137 | dist 138 | 139 | .idea 140 | # End of https://www.gitignore.io/api/node,macos,visualstudiocode 141 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "singleQuote": true, 4 | "trailingComma": "all", 5 | "arrowParens": "always", 6 | "jsxBracketSameLine": false, 7 | "semi": false 8 | } 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # [1.6.0](https://github.com/cschroeter/ts-strictify/compare/v1.5.3...v1.6.0) (2020-06-05) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * disable chalk color coding in test ([3fe254b](https://github.com/cschroeter/ts-strictify/commit/3fe254b98b40b6fc32a528f93ab4be2473c6be34)) 7 | 8 | 9 | ### Features 10 | 11 | * **old-tsc:** filter used flags based on tsc help output ([0040daa](https://github.com/cschroeter/ts-strictify/commit/0040daa6d8accdf195003495dd83955f1d7dcc7d)) 12 | * **old-tsc:** function to check if a flag is supported ([9ffe876](https://github.com/cschroeter/ts-strictify/commit/9ffe876cd60fcd5784ce3e9db5e0170a05b2873c)) 13 | 14 | ## [1.5.3](https://github.com/cschroeter/ts-strictify/compare/v1.5.2...v1.5.3) (2020-05-29) 15 | 16 | 17 | ### Bug Fixes 18 | 19 | * **tsc:** prefer local binary ([6730f46](https://github.com/cschroeter/ts-strictify/commit/6730f462219b44dbc8a0b7281bb1e161df5307de)) 20 | 21 | ## [1.5.2](https://github.com/cschroeter/ts-strictify/compare/v1.5.1...v1.5.2) (2020-03-25) 22 | 23 | 24 | ### Bug Fixes 25 | 26 | * **bug:** 'noImplicitUseStrict cannot be specified with option' error ([1930a55](https://github.com/cschroeter/ts-strictify/commit/1930a5554f021401f75ab8c4c8bee5b7d368fdfb)) 27 | 28 | ## [1.5.1](https://github.com/cschroeter/ts-strictify/compare/v1.5.0...v1.5.1) (2020-03-25) 29 | 30 | 31 | ### Bug Fixes 32 | 33 | * remove onFoundSinceRevision due to issues with some CI pipelines ([d6f74e0](https://github.com/cschroeter/ts-strictify/commit/d6f74e03f6e3a8e2b0d5b67147cbd9c1a419af97)) 34 | 35 | # [1.5.0](https://github.com/cschroeter/ts-strictify/compare/v1.4.1...v1.5.0) (2020-02-13) 36 | 37 | 38 | ### Features 39 | 40 | * exit with code 1 if target branch does not exist ([ddf9da2](https://github.com/cschroeter/ts-strictify/commit/ddf9da2898ac206a85ce5ee9809110ec721dd6dd)) 41 | 42 | ## [1.4.1](https://github.com/cschroeter/ts-strictify/compare/v1.4.0...v1.4.1) (2020-02-10) 43 | 44 | 45 | ### Bug Fixes 46 | 47 | * trigger another build ([8100a84](https://github.com/cschroeter/ts-strictify/commit/8100a844843dcf0cc19d78c54ec5dc27c4e4e5f0)) 48 | 49 | # [1.4.0](https://github.com/cschroeter/ts-strictify/compare/v1.3.0...v1.4.0) (2020-02-10) 50 | 51 | 52 | ### Bug Fixes 53 | 54 | * small fix to trigger new build ([f7809e0](https://github.com/cschroeter/ts-strictify/commit/f7809e04f69571a3cf75eb6aeb634530971582d5)) 55 | * trigger build ([ea9fcdd](https://github.com/cschroeter/ts-strictify/commit/ea9fcdd3b14eced00d74def2bf9cade3e42480a6)) 56 | 57 | 58 | ### Features 59 | 60 | * resolve files located in submodules correctly ([cf54c2e](https://github.com/cschroeter/ts-strictify/commit/cf54c2eab3f22ec6a65904162fb97b851ffbe5d3)) 61 | * **file-detection:** add various options to detect files ([9a695e5](https://github.com/cschroeter/ts-strictify/commit/9a695e5bd99225373e0dde0f3c9476aab18347b9)) 62 | * **file-detection:** improve file detection ([be42919](https://github.com/cschroeter/ts-strictify/commit/be42919a807fec1991495fe4fdd3a70999cadaee)) 63 | 64 | # [1.4.0](https://github.com/cschroeter/ts-strictify/compare/v1.3.0...v1.4.0) (2020-02-10) 65 | 66 | 67 | ### Bug Fixes 68 | 69 | * small fix to trigger new build ([f7809e0](https://github.com/cschroeter/ts-strictify/commit/f7809e04f69571a3cf75eb6aeb634530971582d5)) 70 | 71 | 72 | ### Features 73 | 74 | * resolve files located in submodules correctly ([cf54c2e](https://github.com/cschroeter/ts-strictify/commit/cf54c2eab3f22ec6a65904162fb97b851ffbe5d3)) 75 | * **file-detection:** add various options to detect files ([9a695e5](https://github.com/cschroeter/ts-strictify/commit/9a695e5bd99225373e0dde0f3c9476aab18347b9)) 76 | * **file-detection:** improve file detection ([be42919](https://github.com/cschroeter/ts-strictify/commit/be42919a807fec1991495fe4fdd3a70999cadaee)) 77 | 78 | # [1.4.0](https://github.com/cschroeter/ts-strictify/compare/v1.3.0...v1.4.0) (2020-02-10) 79 | 80 | 81 | ### Bug Fixes 82 | 83 | * small fix to trigger new build ([f7809e0](https://github.com/cschroeter/ts-strictify/commit/f7809e04f69571a3cf75eb6aeb634530971582d5)) 84 | 85 | 86 | ### Features 87 | 88 | * resolve files located in submodules correctly ([cf54c2e](https://github.com/cschroeter/ts-strictify/commit/cf54c2eab3f22ec6a65904162fb97b851ffbe5d3)) 89 | * **file-detection:** add various options to detect files ([9a695e5](https://github.com/cschroeter/ts-strictify/commit/9a695e5bd99225373e0dde0f3c9476aab18347b9)) 90 | * **file-detection:** improve file detection ([be42919](https://github.com/cschroeter/ts-strictify/commit/be42919a807fec1991495fe4fdd3a70999cadaee)) 91 | 92 | # [1.4.0](https://github.com/cschroeter/ts-strictify/compare/v1.3.0...v1.4.0) (2020-02-10) 93 | 94 | 95 | ### Features 96 | 97 | * resolve files located in submodules correctly ([cf54c2e](https://github.com/cschroeter/ts-strictify/commit/cf54c2eab3f22ec6a65904162fb97b851ffbe5d3)) 98 | * **file-detection:** add various options to detect files ([9a695e5](https://github.com/cschroeter/ts-strictify/commit/9a695e5bd99225373e0dde0f3c9476aab18347b9)) 99 | * **file-detection:** improve file detection ([be42919](https://github.com/cschroeter/ts-strictify/commit/be42919a807fec1991495fe4fdd3a70999cadaee)) 100 | 101 | # [1.4.0](https://github.com/cschroeter/ts-strictify/compare/v1.3.0...v1.4.0) (2020-02-10) 102 | 103 | 104 | ### Features 105 | 106 | * **file-detection:** add various options to detect files ([9a695e5](https://github.com/cschroeter/ts-strictify/commit/9a695e5bd99225373e0dde0f3c9476aab18347b9)) 107 | * **file-detection:** improve file detection ([be42919](https://github.com/cschroeter/ts-strictify/commit/be42919a807fec1991495fe4fdd3a70999cadaee)) 108 | 109 | # [1.3.0](https://github.com/cschroeter/ts-strictify/compare/v1.2.0...v1.3.0) (2020-02-10) 110 | 111 | 112 | ### Features 113 | 114 | * **packages:** update dependencies ([066b120](https://github.com/cschroeter/ts-strictify/commit/066b120ce479a964ef9e248dd7433978a526b9c6)) 115 | 116 | # [1.2.0](https://github.com/cschroeter/ts-strictify/compare/v1.1.0...v1.2.0) (2019-10-15) 117 | 118 | 119 | ### Bug Fixes 120 | 121 | * **tests:** set global git config ([3453da2](https://github.com/cschroeter/ts-strictify/commit/3453da283d6b81f56e20b5d336c2eae36b22e4fa)) 122 | 123 | 124 | ### Features 125 | 126 | * **packages:** udpate dependencies ([2d4f871](https://github.com/cschroeter/ts-strictify/commit/2d4f871226dce05f706c12ed657743bc08b05f0c)) 127 | * **tests:** add test setup ([a5b41b4](https://github.com/cschroeter/ts-strictify/commit/a5b41b4202aa54d1ee1609142047b9d30ffb49df)) 128 | * **tests:** add test setup ([82643fe](https://github.com/cschroeter/ts-strictify/commit/82643fe3ffd3d2c6710560f98484506afac9c5a4)) 129 | 130 | # [1.1.0](https://github.com/cschroeter/ts-strictify/compare/v1.0.1...v1.1.0) (2019-10-11) 131 | 132 | 133 | ### Features 134 | 135 | * **cli:** improve visual output ([0598569](https://github.com/cschroeter/ts-strictify/commit/059856994a9c6cb54dc66345ddc1a15e1b8fd805)) 136 | 137 | ## [1.0.1](https://github.com/cschroeter/ts-strictify/compare/v1.0.0...v1.0.1) (2019-10-09) 138 | 139 | 140 | ### Bug Fixes 141 | 142 | * **npm:** add missing files property ([d374b04](https://github.com/cschroeter/ts-strictify/commit/d374b04f26b7b8b607cbdccd66c829a25103d4ed)) 143 | 144 | # 1.0.0 (2019-10-09) 145 | 146 | 147 | ### Features 148 | 149 | * **changelog:** generate changelog ([72267f5](https://github.com/cschroeter/ts-strictify/commit/72267f541f985e45aafa3574cce4949cce7d5d04)) 150 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ts-strictify 2 | 3 | > Runs [TypeScript](hhttp://www.typescriptlang.org/) in strict mode on your changed files. 4 | 5 | ![Demo](./docs/assets/preview.png) 6 | 7 | ## Background 8 | 9 | TBD 10 | 11 | ## How it works 12 | 13 | When you start working on a new feature or fixing a bug, you will modify the code base in one way or another. `ts-strictify` will take a look at these changes - and only these changes (!) and will complain, if the files you have touched are not strict compliant. 14 | 15 | That is different than TypeScript works. You could check a single file against the compiler, but the compiler would also look up the imports and the imports of the imports. Not exactly what you want, when you are looking for incrementally update path. 16 | 17 | Head over to https://cschroeter.net/moving-to-strict-typescript/ for more insights. 18 | 19 | ## Install 20 | 21 | With `yarn`: 22 | 23 | ```shellsession 24 | yarn add --dev ts-strictify 25 | ``` 26 | 27 | With `npm`: 28 | 29 | ```shellsession 30 | npm install --save-dev ts-strictify 31 | ``` 32 | 33 | ## Usage 34 | 35 | With `yarn`: 36 | 37 | ```shellsession 38 | yarn ts-strictify 39 | ``` 40 | 41 | You can also disable a compiler flag, for example you want to disable `strictNullChecks` 42 | 43 | ```shellsession 44 | yarn ts-strictify --strictNullChecks false 45 | ``` 46 | 47 | You can find a list of all available options [`here`](#options). 48 | 49 | With [`npx`](https://npm.im/npx): 50 | 51 | ```shellsession 52 | npx ts-strictify 53 | ``` 54 | 55 | With `npm`: 56 | 57 | 1. Add `"ts-strictify": "ts-strictify"` to the scripts section of `package.json`. 58 | 2. `npm run ts-strictify` 59 | 60 | ## Pre-Commit Hook 61 | 62 | You can run `ts-strictify` as a pre-commit hook using [`husky`](https://github.com/typicode/husky). 63 | 64 | ```shellstream 65 | yarn add --dev husky 66 | ``` 67 | 68 | In `package.json`, add: 69 | 70 | ``` 71 | "husky": { 72 | "hooks": { 73 | "pre-commit": "ts-strictify" 74 | } 75 | } 76 | ``` 77 | 78 | ## Options 79 | 80 | ```bash 81 | Options: 82 | --help Show help [boolean] 83 | --version Show version number [boolean] 84 | --noImplicitAny [boolean] [default: true] 85 | --noImplicitThis [boolean] [default: true] 86 | --alwaysStrict [boolean] [default: true] 87 | --strictBindCallApply [boolean] [default: true] 88 | --strictNullChecks [boolean] [default: true] 89 | --strictFunctionTypes [boolean] [default: true] 90 | --strictPropertyInitialization [boolean] [default: true] 91 | --noEmit [boolean] [default: true] 92 | --targetBranch [string] [default: "master"] 93 | --commitedFiles [boolean] [default: true] 94 | --stagedFiles [boolean] [default: true] 95 | --modifiedFiles [boolean] [default: true] 96 | --untrackedFiles [boolean] [default: true] 97 | --createdFiles [boolean] [default: true] 98 | ``` 99 | 100 | ## Supported SCM 101 | 102 | - Git 103 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'], 3 | } 4 | -------------------------------------------------------------------------------- /docs/assets/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cschroeter/ts-strictify/530b694566f7d75f0e90695318f342eec0d1c4f1/docs/assets/preview.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-strictify", 3 | "version": "1.6.0", 4 | "description": "Enable gradual TypeScript strict", 5 | "keywords": [ 6 | "typescript", 7 | "strict" 8 | ], 9 | "license": "MIT", 10 | "author": "Christian Schröter (https://cschroeter.net)", 11 | "bin": "./dist/cli.js", 12 | "files": [ 13 | "dist" 14 | ], 15 | "engines": { 16 | "node": ">=8.10.0" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/cschroeter/ts-strictify.git" 21 | }, 22 | "scripts": { 23 | "start": "tsc -w", 24 | "build": "tsc", 25 | "test": "jest", 26 | "release": "semantic-release" 27 | }, 28 | "dependencies": { 29 | "chalk": "^3.0.0", 30 | "execa": "^4.0.0", 31 | "lodash": "^4.17.0", 32 | "simple-git": "^1.132.0", 33 | "yargs": "^15.3.0" 34 | }, 35 | "peerDependencies": { 36 | "typescript": "3.x" 37 | }, 38 | "devDependencies": { 39 | "@babel/core": "7.9.0", 40 | "@babel/preset-env": "7.9.0", 41 | "@babel/preset-typescript": "7.9.0", 42 | "@commitlint/cli": "8.3.5", 43 | "@commitlint/config-conventional": "8.3.4", 44 | "@semantic-release/changelog": "5.0.0", 45 | "@semantic-release/commit-analyzer": "8.0.1", 46 | "@semantic-release/git": "9.0.0", 47 | "@semantic-release/npm": "7.0.5", 48 | "@semantic-release/release-notes-generator": "9.0.1", 49 | "@types/fs-extra": "8.1.0", 50 | "@types/jest": "25.1.4", 51 | "@types/lodash": "4.14.149", 52 | "@types/yargs": "15.0.4", 53 | "@typescript-eslint/eslint-plugin": "2.25.0", 54 | "@typescript-eslint/parser": "2.25.0", 55 | "eslint": "6.8.0", 56 | "eslint-config-prettier": "6.10.1", 57 | "eslint-plugin-prettier": "3.1.2", 58 | "fs-extra": "9.0.0", 59 | "husky": "4.2.3", 60 | "jest": "25.1.0", 61 | "prettier": "2.0.2", 62 | "pretty-quick": "2.0.1", 63 | "semantic-release": "17.0.4", 64 | "tmp-promise": "2.0.2", 65 | "typescript": "3.7.5" 66 | }, 67 | "husky": { 68 | "hooks": { 69 | "pre-commit": "pretty-quick --staged", 70 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 71 | } 72 | }, 73 | "commitlint": { 74 | "extends": [ 75 | "@commitlint/config-conventional" 76 | ] 77 | }, 78 | "release": { 79 | "plugins": [ 80 | "@semantic-release/commit-analyzer", 81 | "@semantic-release/release-notes-generator", 82 | "@semantic-release/changelog", 83 | "@semantic-release/npm", 84 | "@semantic-release/git" 85 | ], 86 | "branch": "master" 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/cli.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import chalk from 'chalk' 3 | import yargs from 'yargs' 4 | import { pick } from 'lodash' 5 | import { strictify } from './ts-strictify' 6 | 7 | const run = async (): Promise => { 8 | const argv = yargs 9 | .options({ 10 | noImplicitAny: { type: 'boolean', default: true }, 11 | noImplicitThis: { type: 'boolean', default: true }, 12 | noImplicitUseStrict: { type: 'boolean', default: false }, 13 | alwaysStrict: { type: 'boolean', default: true }, 14 | strictBindCallApply: { type: 'boolean', default: true }, 15 | strictNullChecks: { type: 'boolean', default: true }, 16 | strictFunctionTypes: { type: 'boolean', default: true }, 17 | strictPropertyInitialization: { type: 'boolean', default: true }, 18 | noEmit: { type: 'boolean', default: true }, 19 | targetBranch: { type: 'string', default: 'master' }, 20 | commitedFiles: { type: 'boolean', default: true }, 21 | stagedFiles: { type: 'boolean', default: true }, 22 | modifiedFiles: { type: 'boolean', default: true }, 23 | untrackedFiles: { type: 'boolean', default: true }, 24 | createdFiles: { type: 'boolean', default: true }, 25 | }) 26 | .parserConfiguration({ 27 | 'strip-dashed': true, 28 | }).argv 29 | 30 | const typeScriptOptions = pick(argv, [ 31 | 'noImplicitAny', 32 | 'noImplicitThis', 33 | 'noImplicitUseStrict', 34 | 'alwaysStrict', 35 | 'strictBindCallApply', 36 | 'strictNullChecks', 37 | 'strictFunctionTypes', 38 | 'strictPropertyInitialization', 39 | 'noEmit', 40 | ]) 41 | 42 | const gitOptions = pick(argv, [ 43 | 'commitedFiles', 44 | 'stagedFiles', 45 | 'modifiedFiles', 46 | 'untrackedFiles', 47 | 'createdFiles', 48 | 'targetBranch', 49 | ]) 50 | 51 | const result = await strictify({ 52 | gitOptions, 53 | typeScriptOptions, 54 | onFoundChangedFiles: (changedFiles) => { 55 | console.log( 56 | `🎯 Found ${chalk.bold(String(changedFiles.length))} changed ${ 57 | changedFiles.length === 1 ? 'file' : 'files' 58 | }`, 59 | ) 60 | }, 61 | onExamineFile: (file) => { 62 | console.log(`🔍 Checking ${chalk.bold(file)} ...`) 63 | }, 64 | onCheckFile: (file, hasError) => 65 | hasError 66 | ? console.log(`❌ ${chalk.bold(file)} failed`) 67 | : console.log(`✅ ${chalk.bold(file)} passed`), 68 | }) 69 | 70 | if (result.errors) { 71 | console.log(`💥 ${result.errors} errors found`) 72 | process.exit(1) 73 | } else { 74 | console.log(`🎉 ${chalk.green('All files passed')}`) 75 | } 76 | } 77 | run() 78 | -------------------------------------------------------------------------------- /src/lib/git.ts: -------------------------------------------------------------------------------- 1 | import execa from 'execa' 2 | import simpleGit from 'simple-git/promise' 3 | import { isEmpty, split } from 'lodash' 4 | import { join } from 'path' 5 | 6 | export interface GitOptions { 7 | targetBranch: string 8 | commitedFiles: boolean 9 | stagedFiles: boolean 10 | createdFiles: boolean 11 | modifiedFiles: boolean 12 | untrackedFiles: boolean 13 | } 14 | 15 | export const findGitRootDir = async (): Promise => { 16 | return await execa('git', ['rev-parse', '--show-toplevel']) 17 | .then((resposne) => resposne.stdout) 18 | .catch(() => '') 19 | } 20 | 21 | export const findChangedFiles = async (options: GitOptions): Promise => { 22 | const { 23 | untrackedFiles, 24 | modifiedFiles, 25 | createdFiles, 26 | stagedFiles, 27 | commitedFiles, 28 | targetBranch, 29 | } = options 30 | 31 | const status = await simpleGit().status() 32 | const gitRootDir = await findGitRootDir() 33 | 34 | const commited = await simpleGit() 35 | .diff([`${targetBranch}...`, '--name-only']) 36 | .then((diff) => split(diff, '\n').filter((fileName) => !isEmpty(fileName))) 37 | 38 | return Array.from( 39 | new Set([ 40 | ...(untrackedFiles ? status.not_added : []), 41 | ...(modifiedFiles ? status.modified : []), 42 | ...(createdFiles ? status.created : []), 43 | ...(stagedFiles ? status.staged : []), 44 | ...(commitedFiles ? commited : []), 45 | ]), 46 | ).map((fileName) => join(gitRootDir, fileName)) 47 | } 48 | -------------------------------------------------------------------------------- /src/lib/typescript.ts: -------------------------------------------------------------------------------- 1 | import execa from 'execa' 2 | 3 | export interface TypeScriptOptions { 4 | noImplicitAny: boolean 5 | noImplicitThis: boolean 6 | noImplicitUseStrict: boolean 7 | alwaysStrict: boolean 8 | strictBindCallApply: boolean 9 | strictNullChecks: boolean 10 | strictFunctionTypes: boolean 11 | strictPropertyInitialization: boolean 12 | noEmit: boolean 13 | } 14 | 15 | export const isFlagSupported = (flag: string, helpOutput: string): boolean => { 16 | return helpOutput.includes(flag) 17 | } 18 | 19 | export const compile = async (options: TypeScriptOptions): Promise => { 20 | let flagSupported: (flag: string) => boolean = () => true 21 | try { 22 | const { all: helpOutput } = await execa('tsc', ['--help'], { all: true, preferLocal: true }) 23 | if (helpOutput !== undefined) { 24 | flagSupported = (flag: string): boolean => isFlagSupported(flag, helpOutput) 25 | } 26 | } catch (error) { 27 | // hope we are on a recent tsc 28 | } 29 | 30 | const args = Object.entries(options) 31 | .map(([key, value]) => [key.replace(/^/, '--'), value]) 32 | .filter(([key, _value]) => flagSupported(key)) 33 | .reduce((result, [key, value]) => [...result, key, value], []) 34 | 35 | let tscOutput: string[] = [] 36 | try { 37 | await execa('tsc', args, { all: true, preferLocal: true }) 38 | } catch (error) { 39 | const { all } = error 40 | tscOutput = (all as string).split('\n') 41 | } 42 | return tscOutput 43 | } 44 | -------------------------------------------------------------------------------- /src/ts-strictify.ts: -------------------------------------------------------------------------------- 1 | import { GitOptions, findChangedFiles } from './lib/git' 2 | import { TypeScriptOptions, compile } from './lib/typescript' 3 | import { relative } from 'path' 4 | 5 | export interface Args { 6 | typeScriptOptions: TypeScriptOptions 7 | gitOptions: GitOptions 8 | onFoundChangedFiles: (changedFiles: string[]) => void 9 | onExamineFile: (file: string) => void 10 | onCheckFile: (file: string, hasErrors: boolean) => void 11 | } 12 | 13 | export interface StrictifyResult { 14 | success: boolean 15 | errors: number 16 | } 17 | 18 | export const strictify = async (args: Args): Promise => { 19 | const { onFoundChangedFiles, onCheckFile, typeScriptOptions, gitOptions } = args 20 | 21 | const changedFiles = await findChangedFiles(gitOptions).then((files) => 22 | files.filter((fileName) => Boolean(fileName.match(/\.tsx?$/))), 23 | ) 24 | onFoundChangedFiles(changedFiles) 25 | 26 | if (changedFiles.length === 0) { 27 | return { success: true, errors: 0 } 28 | } 29 | 30 | const tscOut = await compile(typeScriptOptions) 31 | const errorCount = changedFiles.reduce((totalErrorCount, fileName) => { 32 | let errorCount = 0 33 | tscOut.map((line) => { 34 | if (line.includes(relative(process.cwd(), fileName))) { 35 | errorCount === 0 ? onCheckFile(fileName, true) : null 36 | totalErrorCount++ 37 | errorCount++ 38 | console.log(line) 39 | } 40 | }) 41 | errorCount === 0 ? onCheckFile(fileName, false) : null 42 | return totalErrorCount 43 | }, 0) 44 | 45 | return { 46 | success: errorCount === 0, 47 | errors: errorCount, 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/help/help-output-mother.ts: -------------------------------------------------------------------------------- 1 | export const TestedVersions = [ 2 | '0.8.0', 3 | '1.0.0', 4 | '2.0.0', 5 | '2.1.4', // looks like there never was a 2.1.0 6 | '2.6.1', // looks like there never was a 2.6.0 7 | '2.7.1', // looks like there never was a 2.7.0 8 | '3.0.1', // looks like there never was a 3.0.1 9 | '3.2.1', // looks like there never was a 3.2.0 10 | ] as const 11 | export type TestedTscVersion = typeof TestedVersions[number] 12 | 13 | export const helpOutput: Record = { 14 | '0.8.0': `Syntax: tsc [options] [file ..] 15 | 16 | Examples: tsc hello.ts 17 | tsc --out foo.js foo.ts 18 | tsc @args.txt 19 | 20 | Options: 21 | -c, --comments Emit comments to output 22 | --declarations Generates corresponding .d.ts file 23 | -e, --exec Execute the script after compilation 24 | -h, --help Print this message 25 | --module KIND Specify module code generation: "commonjs" (default) or "amd" 26 | --nolib Do not include a default lib.d.ts with global declarations 27 | --out FILE Concatenate and emit output to single file 28 | --target VER Specify ECMAScript target version: "ES3" (default), or "ES5" 29 | -w, --watch Watch output files 30 | @ Insert command line options and files from a file. 31 | ✨ Done in 0.99s.`, 32 | '1.0.0': `Version 1.0.0.0 33 | Syntax: tsc [options] [file ..] 34 | 35 | Examples: tsc hello.ts 36 | tsc --out foo.js foo.ts 37 | tsc @args.txt 38 | 39 | Options: 40 | -d, --declaration Generates corresponding .d.ts file. 41 | -h, --help Print this message. 42 | --mapRoot LOCATION Specifies the location where debugger should locate map files instead of generated locations. 43 | -m KIND, --module KIND Specify module code generation: 'commonjs' or 'amd' 44 | --noImplicitAny Warn on expressions and declarations with an implied 'any' type. 45 | --out FILE Concatenate and emit output to single file. 46 | --outDir DIRECTORY Redirect output structure to the directory. 47 | --removeComments Do not emit comments to output. 48 | --sourcemap Generates corresponding .map file. 49 | --sourceRoot LOCATION Specifies the location where debugger should locate TypeScript files instead of source locations. 50 | -t VERSION, --target VERSION Specify ECMAScript target version: 'ES3' (default), or 'ES5' 51 | -v, --version Print the compiler's version: 1.0.0.0 52 | -w, --watch Watch input files. 53 | @ Insert command line options and files from a file. 54 | ✨ Done in 0.83s.`, 55 | '2.0.0': `Version 2.0.0 56 | Syntax: tsc [options] [file ...] 57 | 58 | Examples: tsc hello.ts 59 | tsc --out file.js file.ts 60 | tsc @args.txt 61 | 62 | Options: 63 | --allowJs Allow javascript files to be compiled. 64 | --allowSyntheticDefaultImports Allow default imports from modules with no default export. This does not affect code emit, just typechecking. 65 | --allowUnreachableCode Do not report errors on unreachable code. 66 | --allowUnusedLabels Do not report errors on unused labels. 67 | --baseUrl Base directory to resolve non-absolute module names. 68 | -d, --declaration Generates corresponding '.d.ts' file. 69 | --experimentalDecorators Enables experimental support for ES7 decorators. 70 | --forceConsistentCasingInFileNames Disallow inconsistently-cased references to the same file. 71 | -h, --help Print this message. 72 | --init Initializes a TypeScript project and creates a tsconfig.json file. 73 | --jsx KIND Specify JSX code generation: 'preserve' or 'react' 74 | --lib Specify library files to be included in the compilation: 75 | 'es5' 'es6' 'es2015' 'es7' 'es2016' 'es2017' 'dom' 'webworker' 'scripthost' 'es2015.core' 'es2015.collection' 'es2015.generator' 'es2015.iterable' 'es2015.promise' 'es2015.proxy' 'es2015.reflect' 'es2015.symbol' 'es2015.symbol.wellknown' 'es2016.array.include' 'es2017.object' 'es2017.sharedmemory' 76 | --mapRoot LOCATION Specify the location where debugger should locate map files instead of generated locations. 77 | --maxNodeModuleJsDepth The maximum dependency depth to search under node_modules and load JavaScript files 78 | -m KIND, --module KIND Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015' 79 | --moduleResolution Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). 80 | --newLine NEWLINE Specify the end of line sequence to be used when emitting files: 'CRLF' (dos) or 'LF' (unix). 81 | --noEmit Do not emit outputs. 82 | --noEmitOnError Do not emit outputs if any errors were reported. 83 | --noFallthroughCasesInSwitch Report errors for fallthrough cases in switch statement. 84 | --noImplicitAny Raise error on expressions and declarations with an implied 'any' type. 85 | --noImplicitReturns Report error when not all code paths in function return a value. 86 | --noImplicitThis Raise error on 'this' expressions with an implied 'any' type. 87 | --noImplicitUseStrict Do not emit 'use strict' directives in module output. 88 | --noUnusedLocals Report Errors on Unused Locals. 89 | --noUnusedParameters Report Errors on Unused Parameters. 90 | --outDir DIRECTORY Redirect output structure to the directory. 91 | --outFile FILE Concatenate and emit output to single file. 92 | --preserveConstEnums Do not erase const enum declarations in generated code. 93 | --pretty Stylize errors and messages using color and context. (experimental) 94 | -p DIRECTORY, --project DIRECTORY Compile the project in the given directory. 95 | --reactNamespace Specify the object invoked for createElement and __spread when targeting 'react' JSX emit 96 | --removeComments Do not emit comments to output. 97 | --rootDir LOCATION Specify the root directory of input files. Use to control the output directory structure with --outDir. 98 | --skipLibCheck Skip type checking of declaration files. 99 | --sourceMap Generates corresponding '.map' file. 100 | --sourceRoot LOCATION Specify the location where debugger should locate TypeScript files instead of source locations. 101 | --strictNullChecks Enable strict null checks. 102 | --suppressImplicitAnyIndexErrors Suppress noImplicitAny errors for indexing objects lacking index signatures. 103 | -t VERSION, --target VERSION Specify ECMAScript target version: 'ES3' (default), 'ES5', or 'ES2015' 104 | --traceResolution Enable tracing of the name resolution process. 105 | --types Type declaration files to be included in compilation. 106 | -v, --version Print the compiler's version. 107 | -w, --watch Watch input files. 108 | @ Insert command line options and files from a file. 109 | ✨ Done in 0.59s. 110 | yarn run v1.22.4`, 111 | '2.1.4': `Version 2.1.4 112 | Syntax: tsc [options] [file ...] 113 | 114 | Examples: tsc hello.ts 115 | tsc --outFile file.js file.ts 116 | tsc @args.txt 117 | 118 | Options: 119 | --allowJs Allow javascript files to be compiled. 120 | --allowSyntheticDefaultImports Allow default imports from modules with no default export. This does not affect code emit, just typechecking. 121 | --allowUnreachableCode Do not report errors on unreachable code. 122 | --allowUnusedLabels Do not report errors on unused labels. 123 | --alwaysStrict Parse in strict mode and emit "use strict" for each source file 124 | --baseUrl Base directory to resolve non-absolute module names. 125 | -d, --declaration Generates corresponding '.d.ts' file. 126 | --experimentalDecorators Enables experimental support for ES7 decorators. 127 | --forceConsistentCasingInFileNames Disallow inconsistently-cased references to the same file. 128 | -h, --help Print this message. 129 | --importHelpers Import emit helpers from 'tslib'. 130 | --init Initializes a TypeScript project and creates a tsconfig.json file. 131 | --jsx KIND Specify JSX code generation: 'preserve' or 'react' 132 | --jsxFactory Specify the JSX factory function to use when targeting 'react' JSX emit, e.g. 'React.createElement' or 'h'. 133 | --lib Specify library files to be included in the compilation: 134 | 'es5' 'es6' 'es2015' 'es7' 'es2016' 'es2017' 'dom' 'dom.iterable' 'webworker' 'scripthost' 'es2015.core' 'es2015.collection' 'es2015.generator' 'es2015.iterable' 'es2015.promise' 'es2015.proxy' 'es2015.reflect' 'es2015.symbol' 'es2015.symbol.wellknown' 'es2016.array.include' 'es2017.object' 'es2017.sharedmemory' 'es2017.string' 135 | --mapRoot LOCATION Specify the location where debugger should locate map files instead of generated locations. 136 | --maxNodeModuleJsDepth The maximum dependency depth to search under node_modules and load JavaScript files 137 | -m KIND, --module KIND Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015' 138 | --moduleResolution STRATEGY Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). 139 | --newLine NEWLINE Specify the end of line sequence to be used when emitting files: 'CRLF' (dos) or 'LF' (unix). 140 | --noEmit Do not emit outputs. 141 | --noEmitOnError Do not emit outputs if any errors were reported. 142 | --noFallthroughCasesInSwitch Report errors for fallthrough cases in switch statement. 143 | --noImplicitAny Raise error on expressions and declarations with an implied 'any' type. 144 | --noImplicitReturns Report error when not all code paths in function return a value. 145 | --noImplicitThis Raise error on 'this' expressions with an implied 'any' type. 146 | --noImplicitUseStrict Do not emit 'use strict' directives in module output. 147 | --noUnusedLocals Report errors on unused locals. 148 | --noUnusedParameters Report errors on unused parameters. 149 | --outDir DIRECTORY Redirect output structure to the directory. 150 | --outFile FILE Concatenate and emit output to single file. 151 | --preserveConstEnums Do not erase const enum declarations in generated code. 152 | --pretty Stylize errors and messages using color and context. (experimental) 153 | -p DIRECTORY, --project DIRECTORY Compile the project in the given directory. 154 | --reactNamespace Specify the object invoked for createElement and __spread when targeting 'react' JSX emit 155 | --removeComments Do not emit comments to output. 156 | --rootDir LOCATION Specify the root directory of input files. Use to control the output directory structure with --outDir. 157 | --skipLibCheck Skip type checking of declaration files. 158 | --sourceMap Generates corresponding '.map' file. 159 | --sourceRoot LOCATION Specify the location where debugger should locate TypeScript files instead of source locations. 160 | --strictNullChecks Enable strict null checks. 161 | --suppressImplicitAnyIndexErrors Suppress noImplicitAny errors for indexing objects lacking index signatures. 162 | -t VERSION, --target VERSION Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT' 163 | --traceResolution Enable tracing of the name resolution process. 164 | --types Type declaration files to be included in compilation. 165 | -v, --version Print the compiler's version. 166 | -w, --watch Watch input files. 167 | @ Insert command line options and files from a file. 168 | ✨ Done in 0.67s.`, 169 | '2.6.1': `Version 2.6.1 170 | Syntax: tsc [options] [file ...] 171 | 172 | Examples: tsc hello.ts 173 | tsc --outFile file.js file.ts 174 | tsc @args.txt 175 | 176 | Options: 177 | -h, --help Print this message. 178 | --all Show all compiler options. 179 | -v, --version Print the compiler's version. 180 | --init Initializes a TypeScript project and creates a tsconfig.json file. 181 | -p FILE OR DIRECTORY, --project FILE OR DIRECTORY Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'. 182 | --pretty Stylize errors and messages using color and context (experimental). 183 | -w, --watch Watch input files. 184 | -t VERSION, --target VERSION Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. 185 | -m KIND, --module KIND Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 186 | --lib Specify library files to be included in the compilation: 187 | 'es5' 'es6' 'es2015' 'es7' 'es2016' 'es2017' 'esnext' 'dom' 'dom.iterable' 'webworker' 'scripthost' 'es2015.core' 'es2015.collection' 'es2015.generator' 'es2015.iterable' 'es2015.promise' 'es2015.proxy' 'es2015.reflect' 'es2015.symbol' 'es2015.symbol.wellknown' 'es2016.array.include' 'es2017.object' 'es2017.sharedmemory' 'es2017.string' 'es2017.intl' 'esnext.asynciterable' 188 | --allowJs Allow javascript files to be compiled. 189 | --jsx KIND Specify JSX code generation: 'preserve', 'react-native', or 'react'. 190 | -d, --declaration Generates corresponding '.d.ts' file. 191 | --sourceMap Generates corresponding '.map' file. 192 | --outFile FILE Concatenate and emit output to single file. 193 | --outDir DIRECTORY Redirect output structure to the directory. 194 | --removeComments Do not emit comments to output. 195 | --noEmit Do not emit outputs. 196 | --strict Enable all strict type-checking options. 197 | --noImplicitAny Raise error on expressions and declarations with an implied 'any' type. 198 | --strictNullChecks Enable strict null checks. 199 | --strictFunctionTypes Enable strict checking of function types. 200 | --noImplicitThis Raise error on 'this' expressions with an implied 'any' type. 201 | --alwaysStrict Parse in strict mode and emit "use strict" for each source file. 202 | --noUnusedLocals Report errors on unused locals. 203 | --noUnusedParameters Report errors on unused parameters. 204 | --noImplicitReturns Report error when not all code paths in function return a value. 205 | --noFallthroughCasesInSwitch Report errors for fallthrough cases in switch statement. 206 | --types Type declaration files to be included in compilation. 207 | @ Insert command line options and files from a file. 208 | ✨ Done in 0.76s.`, 209 | '2.7.1': `Version 2.7.1 210 | Syntax: tsc [options] [file ...] 211 | 212 | Examples: tsc hello.ts 213 | tsc --outFile file.js file.ts 214 | tsc @args.txt 215 | 216 | Options: 217 | -h, --help Print this message. 218 | --all Show all compiler options. 219 | -v, --version Print the compiler's version. 220 | --init Initializes a TypeScript project and creates a tsconfig.json file. 221 | -p FILE OR DIRECTORY, --project FILE OR DIRECTORY Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'. 222 | --pretty Stylize errors and messages using color and context (experimental). 223 | -w, --watch Watch input files. 224 | -t VERSION, --target VERSION Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. 225 | -m KIND, --module KIND Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 226 | --lib Specify library files to be included in the compilation. 227 | 'es5' 'es6' 'es2015' 'es7' 'es2016' 'es2017' 'es2018' 'esnext' 'dom' 'dom.iterable' 'webworker' 'scripthost' 'es2015.core' 'es2015.collection' 'es2015.generator' 'es2015.iterable' 'es2015.promise' 'es2015.proxy' 'es2015.reflect' 'es2015.symbol' 'es2015.symbol.wellknown' 'es2016.array.include' 'es2017.object' 'es2017.sharedmemory' 'es2017.string' 'es2017.intl' 'es2017.typedarrays' 'esnext.array' 'esnext.asynciterable' 'esnext.promise' 228 | --allowJs Allow javascript files to be compiled. 229 | --jsx KIND Specify JSX code generation: 'preserve', 'react-native', or 'react'. 230 | -d, --declaration Generates corresponding '.d.ts' file. 231 | --sourceMap Generates corresponding '.map' file. 232 | --outFile FILE Concatenate and emit output to single file. 233 | --outDir DIRECTORY Redirect output structure to the directory. 234 | --removeComments Do not emit comments to output. 235 | --noEmit Do not emit outputs. 236 | --strict Enable all strict type-checking options. 237 | --noImplicitAny Raise error on expressions and declarations with an implied 'any' type. 238 | --strictNullChecks Enable strict null checks. 239 | --strictFunctionTypes Enable strict checking of function types. 240 | --strictPropertyInitialization Enable strict checking of property initialization in classes. 241 | --noImplicitThis Raise error on 'this' expressions with an implied 'any' type. 242 | --alwaysStrict Parse in strict mode and emit "use strict" for each source file. 243 | --noUnusedLocals Report errors on unused locals. 244 | --noUnusedParameters Report errors on unused parameters. 245 | --noImplicitReturns Report error when not all code paths in function return a value. 246 | --noFallthroughCasesInSwitch Report errors for fallthrough cases in switch statement. 247 | --types Type declaration files to be included in compilation. 248 | --esModuleInterop Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 249 | @ Insert command line options and files from a file. 250 | ✨ Done in 0.57s.`, 251 | '3.0.1': `Version 3.0.1 252 | Syntax: tsc [options] [file...] 253 | 254 | Examples: tsc hello.ts 255 | tsc --outFile file.js file.ts 256 | tsc @args.txt 257 | tsc --build tsconfig.json 258 | 259 | Options: 260 | -h, --help Print this message. 261 | --all Show all compiler options. 262 | -v, --version Print the compiler's version. 263 | --init Initializes a TypeScript project and creates a tsconfig.json file. 264 | -p FILE OR DIRECTORY, --project FILE OR DIRECTORY Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'. 265 | -b, --build Build one or more projects and their dependencies, if out of date 266 | --pretty Stylize errors and messages using color and context (experimental). 267 | -w, --watch Watch input files. 268 | -t VERSION, --target VERSION Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. 269 | -m KIND, --module KIND Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 270 | --lib Specify library files to be included in the compilation. 271 | 'es5' 'es6' 'es2015' 'es7' 'es2016' 'es2017' 'es2018' 'esnext' 'dom' 'dom.iterable' 'webworker' 'webworker.importscripts' 'scripthost' 'es2015.core' 'es2015.collection' 'es2015.generator' 'es2015.iterable' 'es2015.promise' 'es2015.proxy' 'es2015.reflect' 'es2015.symbol' 'es2015.symbol.wellknown' 'es2016.array.include' 'es2017.object' 'es2017.sharedmemory' 'es2017.string' 'es2017.intl' 'es2017.typedarrays' 'es2018.intl' 'es2018.promise' 'es2018.regexp' 'esnext.array' 'esnext.symbol' 'esnext.asynciterable' 'esnext.intl' 272 | --allowJs Allow javascript files to be compiled. 273 | --jsx KIND Specify JSX code generation: 'preserve', 'react-native', or 'react'. 274 | -d, --declaration Generates corresponding '.d.ts' file. 275 | --declarationMap Generates a sourcemap for each corresponding '.d.ts' file. 276 | --sourceMap Generates corresponding '.map' file. 277 | --outFile FILE Concatenate and emit output to single file. 278 | --outDir DIRECTORY Redirect output structure to the directory. 279 | --removeComments Do not emit comments to output. 280 | --noEmit Do not emit outputs. 281 | --strict Enable all strict type-checking options. 282 | --noImplicitAny Raise error on expressions and declarations with an implied 'any' type. 283 | --strictNullChecks Enable strict null checks. 284 | --strictFunctionTypes Enable strict checking of function types. 285 | --strictPropertyInitialization Enable strict checking of property initialization in classes. 286 | --noImplicitThis Raise error on 'this' expressions with an implied 'any' type. 287 | --alwaysStrict Parse in strict mode and emit "use strict" for each source file. 288 | --noUnusedLocals Report errors on unused locals. 289 | --noUnusedParameters Report errors on unused parameters. 290 | --noImplicitReturns Report error when not all code paths in function return a value. 291 | --noFallthroughCasesInSwitch Report errors for fallthrough cases in switch statement. 292 | --types Type declaration files to be included in compilation. 293 | --esModuleInterop Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 294 | @ Insert command line options and files from a file. 295 | ✨ Done in 0.95s.`, 296 | '3.2.1': `Version 3.2.1 297 | Syntax: tsc [options] [file...] 298 | 299 | Examples: tsc hello.ts 300 | tsc --outFile file.js file.ts 301 | tsc @args.txt 302 | tsc --build tsconfig.json 303 | 304 | Options: 305 | -h, --help Print this message. 306 | -w, --watch Watch input files. 307 | --pretty Stylize errors and messages using color and context (experimental). 308 | --all Show all compiler options. 309 | -v, --version Print the compiler's version. 310 | --init Initializes a TypeScript project and creates a tsconfig.json file. 311 | -p FILE OR DIRECTORY, --project FILE OR DIRECTORY Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'. 312 | -b, --build Build one or more projects and their dependencies, if out of date 313 | -t VERSION, --target VERSION Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. 314 | -m KIND, --module KIND Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 315 | --lib Specify library files to be included in the compilation. 316 | 'es5' 'es6' 'es2015' 'es7' 'es2016' 'es2017' 'es2018' 'esnext' 'dom' 'dom.iterable' 'webworker' 'webworker.importscripts' 'scripthost' 'es2015.core' 'es2015.collection' 'es2015.generator' 'es2015.iterable' 'es2015.promise' 'es2015.proxy' 'es2015.reflect' 'es2015.symbol' 'es2015.symbol.wellknown' 'es2016.array.include' 'es2017.object' 'es2017.sharedmemory' 'es2017.string' 'es2017.intl' 'es2017.typedarrays' 'es2018.intl' 'es2018.promise' 'es2018.regexp' 'esnext.array' 'esnext.symbol' 'esnext.asynciterable' 'esnext.intl' 'esnext.bigint' 317 | --allowJs Allow javascript files to be compiled. 318 | --jsx KIND Specify JSX code generation: 'preserve', 'react-native', or 'react'. 319 | -d, --declaration Generates corresponding '.d.ts' file. 320 | --declarationMap Generates a sourcemap for each corresponding '.d.ts' file. 321 | --sourceMap Generates corresponding '.map' file. 322 | --outFile FILE Concatenate and emit output to single file. 323 | --outDir DIRECTORY Redirect output structure to the directory. 324 | --removeComments Do not emit comments to output. 325 | --noEmit Do not emit outputs. 326 | --strict Enable all strict type-checking options. 327 | --noImplicitAny Raise error on expressions and declarations with an implied 'any' type. 328 | --strictNullChecks Enable strict null checks. 329 | --strictFunctionTypes Enable strict checking of function types. 330 | --strictBindCallApply Enable strict 'bind', 'call', and 'apply' methods on functions. 331 | --strictPropertyInitialization Enable strict checking of property initialization in classes. 332 | --noImplicitThis Raise error on 'this' expressions with an implied 'any' type. 333 | --alwaysStrict Parse in strict mode and emit "use strict" for each source file. 334 | --noUnusedLocals Report errors on unused locals. 335 | --noUnusedParameters Report errors on unused parameters. 336 | --noImplicitReturns Report error when not all code paths in function return a value. 337 | --noFallthroughCasesInSwitch Report errors for fallthrough cases in switch statement. 338 | --types Type declaration files to be included in compilation. 339 | --esModuleInterop Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 340 | @ Insert command line options and files from a file. 341 | ✨ Done in 0.51s.`, 342 | } 343 | -------------------------------------------------------------------------------- /tests/repository/src/noImplicitAny.ts: -------------------------------------------------------------------------------- 1 | const foo = (arg): void => {} 2 | -------------------------------------------------------------------------------- /tests/repository/src/strictNullChecks.ts: -------------------------------------------------------------------------------- 1 | interface User { 2 | age?: number 3 | } 4 | const myUser: User = {} 5 | 6 | console.log(myUser.age.toString()) 7 | -------------------------------------------------------------------------------- /tests/repository/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/supported-options.spec.ts: -------------------------------------------------------------------------------- 1 | import { isFlagSupported, TypeScriptOptions } from '../src/lib/typescript' 2 | import { helpOutput, TestedTscVersion, TestedVersions } from './help/help-output-mother' 3 | 4 | type TscFlag = keyof TypeScriptOptions 5 | 6 | const expectToBeSupportedSince = (since: TestedTscVersion, flag: TscFlag): void => { 7 | const flagWithDashes = '--' + flag 8 | const firstSupportedIndex = TestedVersions.indexOf(since) 9 | const unsupported = TestedVersions.slice(0, firstSupportedIndex) 10 | const supported = TestedVersions.slice(firstSupportedIndex) 11 | unsupported.forEach((version) => { 12 | expect(isFlagSupported(flagWithDashes, helpOutput[version])).toBe(false) 13 | }) 14 | supported.forEach((version) => { 15 | expect(isFlagSupported(flagWithDashes, helpOutput[version])).toBe(true) 16 | }) 17 | } 18 | 19 | test('support for --implicitAny', () => { 20 | expectToBeSupportedSince('1.0.0', 'noImplicitAny') 21 | }) 22 | 23 | test('support for --noEmit', () => { 24 | expectToBeSupportedSince('2.0.0', 'noEmit') 25 | }) 26 | 27 | test('support for --noImplicitThis', () => { 28 | expectToBeSupportedSince('2.0.0', 'noImplicitThis') 29 | }) 30 | 31 | test('support for --strictNullChecks', () => { 32 | expectToBeSupportedSince('2.0.0', 'strictNullChecks') 33 | }) 34 | 35 | test('support for --alwaysStrict', () => { 36 | expectToBeSupportedSince('2.1.4', 'alwaysStrict') 37 | }) 38 | 39 | test('support for --strictFunctionTypes', () => { 40 | expectToBeSupportedSince('2.6.1', 'strictFunctionTypes') 41 | }) 42 | 43 | test('support for --strictBindCallApply', () => { 44 | expectToBeSupportedSince('3.2.1', 'strictBindCallApply') 45 | }) 46 | -------------------------------------------------------------------------------- /tests/ts-strictify.spec.ts: -------------------------------------------------------------------------------- 1 | import simpleGit from 'simple-git/promise' 2 | import tmp from 'tmp-promise' 3 | import { TypeScriptOptions } from '../src/lib/typescript' 4 | import { GitOptions } from '../src/lib/git' 5 | 6 | import execa from 'execa' 7 | import { join } from 'path' 8 | import { copy, outputFile } from 'fs-extra' 9 | 10 | const runTsStrictifyInPath = async ( 11 | path: string, 12 | options: Partial = {}, 13 | ): Promise => { 14 | const cwd = process.cwd() 15 | const tsStrictify = join(cwd, 'dist/cli.js') 16 | 17 | const args = Object.entries(options) 18 | .map(([key, value]) => [key.replace(/^/, '--'), value]) 19 | .reduce((result, [key, value]) => [...result, key.toString(), value.toString()], []) 20 | 21 | process.chdir(path) 22 | return execa('node', [tsStrictify, ...args], { 23 | env: { 24 | //the assertions break in an environment that supports color 25 | //override chalk color detection https://github.com/chalk/supports-color/blob/master/index.js 26 | FORCE_COLOR: 'false', 27 | }, 28 | }) 29 | .then((response) => response.stdout) 30 | .catch((error) => error.stdout) 31 | .finally(() => process.chdir(cwd)) 32 | } 33 | 34 | test('files are detected correctly', async () => { 35 | jest.setTimeout(20000) 36 | const { path } = await tmp.dir() 37 | const git = simpleGit(path) 38 | 39 | await git 40 | .init() 41 | .then(() => git.addConfig('user.name', 'Some One')) 42 | .then(() => git.addConfig('user.email', 'some@one.com')) 43 | .then(() => copy(join(__dirname, 'repository'), path)) 44 | .then(() => git.add('./*')) 45 | .then(() => git.commit('First commit')) 46 | .then(() => runTsStrictifyInPath(path)) 47 | .then((stdout) => expect(stdout).toMatch(/Found 0 changed file/)) 48 | 49 | await git 50 | .checkoutLocalBranch('feature') 51 | .then(() => outputFile(join(path, 'foo.ts'), 'const foo = (arg): void => {}')) 52 | .then(() => runTsStrictifyInPath(path)) 53 | .then((stdout) => { 54 | expect(stdout).toMatch(/Found 1 changed file/) 55 | expect(stdout).toMatch(/error TS7006: Parameter 'arg' implicitly has an 'any' type/) 56 | }) 57 | .then(() => runTsStrictifyInPath(path, { untrackedFiles: false })) 58 | .then((stdout) => { 59 | expect(stdout).toMatch(/Found 0 changed file/) 60 | }) 61 | 62 | await git 63 | .add('./*') 64 | .then(() => runTsStrictifyInPath(path)) 65 | .then((stdout) => expect(stdout).toMatch(/Found 1 changed file/)) 66 | .then(() => runTsStrictifyInPath(path, { createdFiles: false })) 67 | .then((stdout) => { 68 | expect(stdout).toMatch(/Found 0 changed file/) 69 | }) 70 | 71 | await git 72 | .commit('Second commit') 73 | .then(() => runTsStrictifyInPath(path)) 74 | .then((stdout) => expect(stdout).toMatch(/Found 1 changed file/)) 75 | .then(() => runTsStrictifyInPath(path, { commitedFiles: false })) 76 | .then((stdout) => { 77 | expect(stdout).toMatch(/Found 0 changed file/) 78 | }) 79 | }) 80 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "moduleResolution": "node", 7 | "downlevelIteration": true, 8 | "target": "es2017", 9 | "outDir": "dist" 10 | }, 11 | "include": ["src/**/*"] 12 | } 13 | --------------------------------------------------------------------------------