diff --git a/packages/example-ts4/.babelrc b/packages/example-ts4/.babelrc new file mode 100644 index 0000000..937768f --- /dev/null +++ b/packages/example-ts4/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["@babel/preset-env", "@babel/preset-typescript"] +} \ No newline at end of file diff --git a/packages/example-ts4/README.md b/packages/example-ts4/README.md new file mode 100644 index 0000000..16dd4cb --- /dev/null +++ b/packages/example-ts4/README.md @@ -0,0 +1,18 @@ +# ts-overrides-plugin example + +Before all: + +```bash +yarn ts-patch install +``` + +Commands: + +```bash +yarn build:tsc +yarn build:ts-loader +yarn build:fork-ts +yarn watch:tsc +yarn watch:ts-loader +yarn watch:fork-ts +``` diff --git a/packages/example-ts4/package.json b/packages/example-ts4/package.json new file mode 100644 index 0000000..201e993 --- /dev/null +++ b/packages/example-ts4/package.json @@ -0,0 +1,29 @@ +{ + "name": "example-ts4", + "scripts": { + "build:tsc": "tsc", + "build:ts-loader": "webpack --config webpack.config.ts-loader.js", + "build:fork-ts": "webpack --config webpack.config.fork-ts.js", + "watch:tsc": "tsc --watch", + "watch:ts-loader": "webpack --config webpack.config.ts-loader.js --watch", + "watch:fork-ts": "webpack --config webpack.config.fork-ts.js --watch", + "prepare": "ts-patch install -s" + }, + "devDependencies": { + "@babel/core": "^7.23.6", + "@babel/preset-env": "^7.23.6", + "@babel/preset-typescript": "^7.23.3", + "@types/babel__core": "^7", + "@types/babel__preset-env": "^7", + "babel-loader": "^9.1.3", + "fork-ts-checker-webpack-plugin": "^9.0.2", + "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", + "ts-overrides-plugin": "workspce:*", + "ts-patch": "2.1.0", + "typescript": "4.2.4", + "webpack": "^5.89.0", + "webpack-cli": "^5.1.4" + }, + "packageManager": "yarn@4.0.2" +} diff --git a/packages/example-ts4/src/index.ts b/packages/example-ts4/src/index.ts new file mode 100644 index 0000000..8f3b5fc --- /dev/null +++ b/packages/example-ts4/src/index.ts @@ -0,0 +1,4 @@ +import { getDate as getDateLegacy } from './legacy/getDate'; +import { getDate as getDateModern } from './modern/getDate'; + +console.log({ getDateLegacy, getDateModern }); \ No newline at end of file diff --git a/packages/example-ts4/src/legacy/getDate.ts b/packages/example-ts4/src/legacy/getDate.ts new file mode 100644 index 0000000..2b74ad3 --- /dev/null +++ b/packages/example-ts4/src/legacy/getDate.ts @@ -0,0 +1,16 @@ +// ok with strict: false +export const getDate = (date) => { + const modern: string | undefined = undefined; + + // ok with strict: false + modern.split(''); + + return date.toLocaleDateString('ru-RU', { + day: 'numeric', + month: 'long', + year: 'numeric', + }); +} + +// show `string` on hover in IDE +export const someVar: string | undefined = undefined; diff --git a/packages/example-ts4/src/modern/getDate.ts b/packages/example-ts4/src/modern/getDate.ts new file mode 100644 index 0000000..9891742 --- /dev/null +++ b/packages/example-ts4/src/modern/getDate.ts @@ -0,0 +1,18 @@ +import { someVar } from '../legacy/getDate'; + +// Parameter 'date' implicitly has an 'any' type. +export const getDate = (date) => { + const modern: string | undefined = undefined; + + // Show `string | undefined` on hover in IDE + console.log(someVar); + + // 'modern' is possibly 'undefined' + modern.split(''); + + return date.toLocaleDateString('ru-RU', { + day: 'numeric', + month: 'long', + year: 'numeric', + }); +} diff --git a/packages/example-ts4/tsconfig.json b/packages/example-ts4/tsconfig.json new file mode 100644 index 0000000..412eb19 --- /dev/null +++ b/packages/example-ts4/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "module": "ESNext", + "outDir": "./dist", + "baseUrl": "./src", + "strict": false, + "noEmit": false, + "skipLibCheck": true, + "plugins": [ + { + "name": "ts-overrides-plugin", + "transform": "ts-overrides-plugin/cli", + "transformProgram": true, + "overrides": [ + { + "files": ["src/modern/**/*.{ts,tsx}"], + "compilerOptions": { + "strict": true, + }, + }, + ] + }, + ] + }, +} diff --git a/packages/example-ts4/webpack.config.fork-ts.js b/packages/example-ts4/webpack.config.fork-ts.js new file mode 100644 index 0000000..f5000f2 --- /dev/null +++ b/packages/example-ts4/webpack.config.fork-ts.js @@ -0,0 +1,29 @@ +const path = require('path'); +const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); + +module.exports = [ + { + mode: 'production', + entry: './src/index.ts', + output: { + path: path.join(__dirname, 'build'), + filename: 'main.js', + }, + module: { + rules: [ + { + test: /\.ts$/, + exclude: /node_modules/, + loader: 'babel-loader', + }, + ], + }, + plugins: [ + new ForkTsCheckerWebpackPlugin(), + ], + resolve: { + extensions: ['.ts', '.js'], + }, + target: 'web', + } +]; diff --git a/packages/example-ts4/webpack.config.ts-loader.js b/packages/example-ts4/webpack.config.ts-loader.js new file mode 100644 index 0000000..8584b36 --- /dev/null +++ b/packages/example-ts4/webpack.config.ts-loader.js @@ -0,0 +1,25 @@ +const path = require('path'); + +module.exports = [ + { + mode: 'production', + entry: './src/index.ts', + output: { + path: path.join(__dirname, 'build'), + filename: 'main.js', + }, + module: { + rules: [ + { + test: /\.ts$/, + exclude: /node_modules/, + loader: 'ts-loader', + }, + ], + }, + resolve: { + extensions: ['.ts', '.js'], + }, + target: 'web', + } +]; diff --git a/packages/plugin/README.md b/packages/plugin/README.md index 28b9e8b..60372e5 100644 --- a/packages/plugin/README.md +++ b/packages/plugin/README.md @@ -29,6 +29,7 @@ any other cases where you need to override the `tsconfig` settings for specific ## Installation and setup Examples can be seen in the [`example`](https://github.com/DiFuks/ts-overrides-plugin/tree/main/packages/example) folder. +Specially for TS4, a separate [`example`](https://github.com/DiFuks/ts-overrides-plugin/tree/main/packages/example-ts4) folder. ### For using the plugin only in the IDE @@ -111,7 +112,11 @@ In the `tsconfig.json` file, add: ``` If you are using [`Persistent Patch`](https://github.com/nonara/ts-patch?tab=readme-ov-file#method-2-persistent-patch) -with `ts-patch`, then there is nothing more to do. If, however, you are using [`Live Compiler`](https://github.com/nonara/ts-patch?tab=readme-ov-file#method-1-live-compiler), the +with `ts-patch`, then there is nothing more to do. + +For TS4 version, it is possible to use only the Persistent Patch option with [ts-patch version 2.1.0](https://github.com/nonara/ts-patch/tree/v2.1.0). + +If, however, you are using [`Live Compiler`](https://github.com/nonara/ts-patch?tab=readme-ov-file#method-1-live-compiler), the following steps are necessary: For the `tsc` command – replace it with `tspc` in `package.json`: diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 0730519..e0454a4 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -43,8 +43,8 @@ "typescript": "5.5.1-rc" }, "peerDependencies": { - "ts-patch": "^3.0.0", - "typescript": "^5.0.0" + "ts-patch": "^3.0.0 || ^2.0.0", + "typescript": "^5.0.0 || ^4.0.0" }, "license": "MIT", "packageManager": "yarn@4.0.2" diff --git a/packages/plugin/src/ide/index.ts b/packages/plugin/src/ide/index.ts index f6ac256..188959e 100644 --- a/packages/plugin/src/ide/index.ts +++ b/packages/plugin/src/ide/index.ts @@ -2,7 +2,7 @@ import { relative } from 'node:path'; import outmatch from 'outmatch'; import type ts from 'typescript/lib/tsserverlibrary'; -import { type Override } from '../types/Override'; +import type { Override } from '../types/Override'; interface IdePluginConfig { overrides: Override[]; @@ -16,13 +16,17 @@ const getOverrideLanguageServices = ( ): ts.LanguageService[] => [...overridesFromConfig].reverse().map(override => { const overrideLanguageServiceHost: ts.LanguageServiceHost = { - fileExists: path => languageServiceHost.fileExists(path), + // don't remove this, it's needed for TS 4 + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + fileExists: path => !!languageServiceHost.fileExists?.(path), getCurrentDirectory: (): string => languageServiceHost.getCurrentDirectory(), getDefaultLibFileName: (options: ts.CompilerOptions): string => languageServiceHost.getDefaultLibFileName(options), getScriptSnapshot: fileName => languageServiceHost.getScriptSnapshot(fileName), getScriptVersion: fileName => languageServiceHost.getScriptVersion(fileName), - readFile: (path, encoding) => languageServiceHost.readFile(path, encoding), + // don't remove this, it's needed for TS 4 + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + readFile: (path, encoding) => languageServiceHost.readFile?.(path, encoding), getCompilationSettings: () => ({ ...languageServiceHost.getCompilationSettings(), ...typescript.convertCompilerOptionsFromJson( diff --git a/packages/plugin/src/types/Override.ts b/packages/plugin/src/types/Override.ts index 51f904a..b8c08aa 100644 --- a/packages/plugin/src/types/Override.ts +++ b/packages/plugin/src/types/Override.ts @@ -1,4 +1,4 @@ -import type ts from 'typescript'; +import type ts from 'typescript/lib/tsserverlibrary'; export interface Override { files: string[]; diff --git a/yarn.lock b/yarn.lock index 2e08bd9..7691c70 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3906,6 +3906,27 @@ __metadata: languageName: node linkType: hard +"example-ts4@workspace:packages/example-ts4": + version: 0.0.0-use.local + resolution: "example-ts4@workspace:packages/example-ts4" + dependencies: + "@babel/core": "npm:^7.23.6" + "@babel/preset-env": "npm:^7.23.6" + "@babel/preset-typescript": "npm:^7.23.3" + "@types/babel__core": "npm:^7" + "@types/babel__preset-env": "npm:^7" + babel-loader: "npm:^9.1.3" + fork-ts-checker-webpack-plugin: "npm:^9.0.2" + ts-loader: "npm:^9.5.1" + ts-node: "npm:^10.9.2" + ts-overrides-plugin: "workspce:*" + ts-patch: "npm:2.1.0" + typescript: "npm:4.2.4" + webpack: "npm:^5.89.0" + webpack-cli: "npm:^5.1.4" + languageName: unknown + linkType: soft + "example@workspace:packages/example": version: 0.0.0-use.local resolution: "example@workspace:packages/example" @@ -4295,7 +4316,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.1.3": +"glob@npm:^7.0.0, glob@npm:^7.1.3": version: 7.2.3 resolution: "glob@npm:7.2.3::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Fglob%2F-%2Fglob-7.2.3.tgz" dependencies: @@ -4309,6 +4330,19 @@ __metadata: languageName: node linkType: hard +"glob@npm:^8.0.3": + version: 8.1.0 + resolution: "glob@npm:8.1.0::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Fglob%2F-%2Fglob-8.1.0.tgz" + dependencies: + fs.realpath: "npm:^1.0.0" + inflight: "npm:^1.0.4" + inherits: "npm:2" + minimatch: "npm:^5.0.1" + once: "npm:^1.3.0" + checksum: 10c0/cb0b5cab17a59c57299376abe5646c7070f8acb89df5595b492dba3bfb43d301a46c01e5695f01154e6553168207cb60d4eaf07d3be4bc3eb9b0457c5c561d0f + languageName: node + linkType: hard + "global-prefix@npm:^3.0.0": version: 3.0.0 resolution: "global-prefix@npm:3.0.0::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Fglobal-prefix%2F-%2Fglobal-prefix-3.0.0.tgz" @@ -4578,6 +4612,13 @@ __metadata: languageName: node linkType: hard +"interpret@npm:^1.0.0": + version: 1.4.0 + resolution: "interpret@npm:1.4.0::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Finterpret%2F-%2Finterpret-1.4.0.tgz" + checksum: 10c0/08c5ad30032edeec638485bc3f6db7d0094d9b3e85e0f950866600af3c52e9fd69715416d29564731c479d9f4d43ff3e4d302a178196bdc0e6837ec147640450 + languageName: node + linkType: hard + "interpret@npm:^3.1.1": version: 3.1.1 resolution: "interpret@npm:3.1.1" @@ -5318,6 +5359,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^5.0.1": + version: 5.1.6 + resolution: "minimatch@npm:5.1.6::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Fminimatch%2F-%2Fminimatch-5.1.6.tgz" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10c0/3defdfd230914f22a8da203747c42ee3c405c39d4d37ffda284dac5e45b7e1f6c49aa8be606509002898e73091ff2a3bbfc59c2c6c71d4660609f63aa92f98e3 + languageName: node + linkType: hard + "minimist@npm:^1.2.0, minimist@npm:^1.2.6, minimist@npm:^1.2.8": version: 1.2.8 resolution: "minimist@npm:1.2.8::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Fminimist%2F-%2Fminimist-1.2.8.tgz" @@ -5898,6 +5948,15 @@ __metadata: languageName: node linkType: hard +"rechoir@npm:^0.6.2": + version: 0.6.2 + resolution: "rechoir@npm:0.6.2::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Frechoir%2F-%2Frechoir-0.6.2.tgz" + dependencies: + resolve: "npm:^1.1.6" + checksum: 10c0/22c4bb32f4934a9468468b608417194f7e3ceba9a508512125b16082c64f161915a28467562368eeb15dc16058eb5b7c13a20b9eb29ff9927d1ebb3b5aa83e84 + languageName: node + linkType: hard + "rechoir@npm:^0.8.0": version: 0.8.0 resolution: "rechoir@npm:0.8.0" @@ -6051,9 +6110,9 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.14.2, resolve@npm:^1.20.0": +"resolve@npm:^1.1.6, resolve@npm:^1.22.1, resolve@npm:^1.22.2, resolve@npm:^1.22.4": version: 1.22.8 - resolution: "resolve@npm:1.22.8" + resolution: "resolve@npm:1.22.8::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Fresolve%2F-%2Fresolve-1.22.8.tgz" dependencies: is-core-module: "npm:^2.13.0" path-parse: "npm:^1.0.7" @@ -6064,9 +6123,9 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.22.2, resolve@npm:^1.22.4": +"resolve@npm:^1.14.2, resolve@npm:^1.20.0": version: 1.22.8 - resolution: "resolve@npm:1.22.8::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Fresolve%2F-%2Fresolve-1.22.8.tgz" + resolution: "resolve@npm:1.22.8" dependencies: is-core-module: "npm:^2.13.0" path-parse: "npm:^1.0.7" @@ -6090,9 +6149,9 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin": +"resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.2#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin": version: 1.22.8 - resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" + resolution: "resolve@patch:resolve@npm%3A1.22.8%3A%3A__archiveUrl=https%253A%252F%252Fregistry.npmjs.org%252Fresolve%252F-%252Fresolve-1.22.8.tgz#optional!builtin::version=1.22.8&hash=c3c19d" dependencies: is-core-module: "npm:^2.13.0" path-parse: "npm:^1.0.7" @@ -6103,9 +6162,9 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A^1.22.2#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin": +"resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin": version: 1.22.8 - resolution: "resolve@patch:resolve@npm%3A1.22.8%3A%3A__archiveUrl=https%253A%252F%252Fregistry.npmjs.org%252Fresolve%252F-%252Fresolve-1.22.8.tgz#optional!builtin::version=1.22.8&hash=c3c19d" + resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" dependencies: is-core-module: "npm:^2.13.0" path-parse: "npm:^1.0.7" @@ -6321,6 +6380,19 @@ __metadata: languageName: node linkType: hard +"shelljs@npm:^0.8.5": + version: 0.8.5 + resolution: "shelljs@npm:0.8.5::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Fshelljs%2F-%2Fshelljs-0.8.5.tgz" + dependencies: + glob: "npm:^7.0.0" + interpret: "npm:^1.0.0" + rechoir: "npm:^0.6.2" + bin: + shjs: bin/shjs + checksum: 10c0/feb25289a12e4bcd04c40ddfab51aff98a3729f5c2602d5b1a1b95f6819ec7804ac8147ebd8d9a85dfab69d501bcf92d7acef03247320f51c1552cec8d8e2382 + languageName: node + linkType: hard + "side-channel@npm:^1.0.4, side-channel@npm:^1.0.6": version: 1.0.6 resolution: "side-channel@npm:1.0.6::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Fside-channel%2F-%2Fside-channel-1.0.6.tgz" @@ -6729,11 +6801,30 @@ __metadata: ts-patch: "npm:3.2.0" typescript: "npm:5.5.1-rc" peerDependencies: - ts-patch: ^3.0.0 - typescript: ^5.0.0 + ts-patch: ^3.0.0 || ^2.0.0 + typescript: ^5.0.0 || ^4.0.0 languageName: unknown linkType: soft +"ts-patch@npm:2.1.0": + version: 2.1.0 + resolution: "ts-patch@npm:2.1.0::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Fts-patch%2F-%2Fts-patch-2.1.0.tgz" + dependencies: + chalk: "npm:^4.1.2" + glob: "npm:^8.0.3" + global-prefix: "npm:^3.0.0" + minimist: "npm:^1.2.6" + resolve: "npm:^1.22.1" + shelljs: "npm:^0.8.5" + strip-ansi: "npm:^6.0.1" + peerDependencies: + typescript: ">=4.0.0" + bin: + ts-patch: bin/cli.js + checksum: 10c0/fb6888807cc7294ea24042519bb520c622ca34c5bc925f70ba35b26c8275ac26d2e78d9642c1885802d444841c9406932292b10a8f7d450ec8d457ba8569a838 + languageName: node + linkType: hard + "ts-patch@npm:3.2.0": version: 3.2.0 resolution: "ts-patch@npm:3.2.0::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Fts-patch%2F-%2Fts-patch-3.2.0.tgz" @@ -6856,6 +6947,16 @@ __metadata: languageName: node linkType: hard +"typescript@npm:4.2.4": + version: 4.2.4 + resolution: "typescript@npm:4.2.4::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Ftypescript%2F-%2Ftypescript-4.2.4.tgz" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/add3dcc8661784e2959d8411f6a2f1c75b063532aae0112bed4a217f58c0f6da194da6a05bc40dc1b2b171e5c595e88370d5fa97fdb680c47fbb8fab4190e02d + languageName: node + linkType: hard + "typescript@npm:5.5.1-rc": version: 5.5.1-rc resolution: "typescript@npm:5.5.1-rc::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Ftypescript%2F-%2Ftypescript-5.5.1-rc.tgz" @@ -6866,6 +6967,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@npm%3A4.2.4#optional!builtin": + version: 4.2.4 + resolution: "typescript@patch:typescript@npm%3A4.2.4%3A%3A__archiveUrl=https%253A%252F%252Fregistry.npmjs.org%252Ftypescript%252F-%252Ftypescript-4.2.4.tgz#optional!builtin::version=4.2.4&hash=334f98" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/c18a8bba07cbc5918f6224238199af421dd94a08e3342f5af269297ddf69eafe3fbaea560eb81def28382a420617844ee16740cced11895d3f1821943d1b00e7 + languageName: node + linkType: hard + "typescript@patch:typescript@npm%3A5.5.1-rc#optional!builtin": version: 5.5.1-rc resolution: "typescript@patch:typescript@npm%3A5.5.1-rc%3A%3A__archiveUrl=https%253A%252F%252Fregistry.npmjs.org%252Ftypescript%252F-%252Ftypescript-5.5.1-rc.tgz#optional!builtin::version=5.5.1-rc&hash=b45daf"