You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+123-8Lines changed: 123 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,7 +14,7 @@ Are meant to be used with javascript code, not typescript code, hence they're ha
14
14
npm install --save-dev @voxpelli/tsconfig
15
15
```
16
16
17
-
Then in your `tsconfig.json`, it [`extends`](https://www.typescriptlang.org/tsconfig#extends)the chosen base config:
17
+
Then add an [`extends`](https://www.typescriptlang.org/tsconfig#extends)to your `tsconfig.json` like this:
18
18
19
19
```json
20
20
{
@@ -32,20 +32,22 @@ Then in your `tsconfig.json`, it [`extends`](https://www.typescriptlang.org/tsco
32
32
33
33
### Generic ones
34
34
35
-
*[`base`](base.json) – where most of the configuration is set
36
-
*[`legacy`](legacy.json) – like `base` but for older TypeScript versions – version 4.5 and onward
37
-
*[`recommended`](recommended.json) – like `base` but adds a [`target`](https://www.typescriptlang.org/tsconfig#target) set to `ES2015`
35
+
*[`base-node-bare`](base-node-bare.json) – where most of the configuration is set (Node.js focused)
36
+
*[`base-node-jsdoc`](base-node-jsdoc.json) – adds JSDoc related config to `base-node-bare`
38
37
39
38
### Node specific ones
40
39
41
-
These extends `base` with the correct [`lib`](https://www.typescriptlang.org/tsconfig#lib)and [`target`](https://www.typescriptlang.org/tsconfig#target) for the node.js version.
40
+
These extends `base-node-jsdoc` with the correct [`lib`](https://www.typescriptlang.org/tsconfig#lib), [`module`](https://www.typescriptlang.org/tsconfig#module), [`moduleResolution`](https://www.typescriptlang.org/tsconfig#moduleResolution)and [`target`](https://www.typescriptlang.org/tsconfig#target) for each Node.js version.
42
41
43
42
Inspired by [tsconfig/bases](https://github.com/tsconfig/bases).
44
43
45
-
*[`node20`](node20.json)
44
+
*[`node14`](node14.json)_deprecated_
45
+
*[`node16`](node16.json)_deprecated_
46
46
*[`node18`](node18.json)
47
-
*[`node16`](node16.json)
48
-
*[`node14`](node14.json)
47
+
*[`node20`](node20.json)
48
+
*[`node22`](node22.json)
49
+
*[`node24`](node24.json)
50
+
*[`nodenext`](nodenext.json) (currently an alias for `base-node-jsdoc`)
49
51
50
52
## Can I use this in my own project?
51
53
@@ -55,6 +57,119 @@ Just as with [voxpelli/eslint-config](https://github.com/voxpelli/eslint-config)
55
57
56
58
Give me a ping if you use it, would be a delight to know you like it 🙂
57
59
60
+
## Generate types
61
+
62
+
When publishing a module, no matter if we use JSDoc or TS syntax we need to publish type declarations.
63
+
64
+
Here's how to generate type declarations when using JSDoc,
65
+
66
+
### 1. Declaration specific config file
67
+
68
+
Add a new declaration specific tsconfig (eg. `declaration.tsconfig.json`) that extends your base tsconfig. Something like:
69
+
70
+
```json
71
+
{
72
+
"extends": "./tsconfig",
73
+
"files": [],
74
+
"exclude": [
75
+
"test/**/*.js"
76
+
],
77
+
"compilerOptions": {
78
+
"declaration": true,
79
+
"declarationMap": true,
80
+
"noEmit": false,
81
+
"emitDeclarationOnly": true
82
+
}
83
+
}
84
+
```
85
+
86
+
The above excludes all top level files and all files in `test/` from having types generated. If one wants eg. `index.js` to have auto-generated types, then one needs to either remove `"files": [],` to use the inherited value or explicitly add it (`"files": ["index.js"],`).
87
+
88
+
If one uses eg. [`@deprecated`](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#deprecated) and wants to retain JSDoc comments in ones type declarations, then one should set [`"removeComments": false`](https://www.typescriptlang.org/tsconfig/#removeComments) in the `compilerOptions`. By default `@voxpelli/tsconfig` sets `"removeComments": true` to keep generated types lean and DRY.
89
+
90
+
### 2. Add scripts
91
+
92
+
We should add scripts that uses the config file. These are examples add them to `"scripts"` in `package.json` and uses [`npm-run-all2`](https://github.com/bcomnes/npm-run-all2) to give clean separation and enable parallel execution.
When we run `build` we sequentially run all `build:*` using [`run-s`](https://github.com/bcomnes/npm-run-all2/blob/e9ca500b9a5f2d4550f4a72020afc1cd8d68b281/docs/run-s.md).
103
+
104
+
1. First we run `clean` to remove any pre-existing generated type declarations (as else they will be used as the source)
105
+
2. Then we run `tsc` which generates the new type declarations thanks to it using the declaration specific tsconfig
When we run `clean` we run all `clean:*` in parallel using [`run-p`](https://github.com/bcomnes/npm-run-all2/blob/e9ca500b9a5f2d4550f4a72020afc1cd8d68b281/docs/run-p.md).
116
+
117
+
Both clean commands use `rm -f` to delete a list of files found through `find`. The `-f` flag is needed since `find` may return an empty list, which without `-f` causes `rm` to fail.
118
+
119
+
The `find` command returns all matching type declaration files. It uses three flags:
120
+
121
+
*`-maxdepth 1'` is used when running in `.` to avoid recursing into `node_modules` (as we of course do _not_ want to remove any type declarations in there)
122
+
*`-name '*.d.ts*'` limits matching file names to `.d.ts` and `.d.ts.map` files. (If you generate `.mts` or `.cts` as well, then change this to `*.d.*ts*`)
123
+
*`-type f` ensures that only files are returned
124
+
125
+
The two clean scripts are:
126
+
127
+
*`clean:declarations-top` cleans all top level (`.`) type declarations except for `index.d.ts` (as that's often hand coded instead). One can remove the `! -name 'index.d.ts'` or add additional `! -name` sections to tweak what is ignored.
128
+
*`clean:declarations-lib` recursively cleans all type declarations in `lib` except for those ending with `-types.d.ts` (as our naming convention is that all such files are hand coded). One can add additional `! -name` sections to ignore further files.
129
+
130
+
#### Tweak type validation scripts
131
+
132
+
Assuming that we have something like the following that checks our types (if you're not using [`type-coverage`](https://github.com/plantain-00/type-coverage) you should start!):
Then we should make sure that we run `clean` before we run our checks as else `tsc` will use the type declarations rather than the JSDoc types when validating.
140
+
141
+
So we should do something like the following, it first runs `clean`, then runs `check:*` in parallel.
142
+
143
+
```json
144
+
"check": "run-s clean && run-p check:*",
145
+
```
146
+
147
+
#### Ensure we generate before publish
148
+
149
+
Lastly we should make sure that we generate the files before publish, something we can do by eg. adding a [`prepublishOnly`](https://docs.npmjs.com/cli/v8/using-npm/scripts#life-cycle-scripts) life cyle script:
150
+
151
+
```json
152
+
"prepublishOnly": "run-s build",
153
+
```
154
+
155
+
### 3. Ignore files in `.gitignore`
156
+
157
+
And something like this in your `.gitignore`:
158
+
159
+
```gitignore
160
+
# Generated types
161
+
*.d.ts
162
+
*.d.ts.map
163
+
!/lib/**/*-types.d.ts
164
+
!/index.d.ts
165
+
```
166
+
167
+
The ignores here (`!/lib/**/*-types.d.ts`, `!/index.d.ts`) matches the ignores we added in our [`clean:*`](#2-add-scripts) scripts
168
+
169
+
### Reference example
170
+
171
+
See my [`voxpelli/node-module-template`](https://github.com/voxpelli/node-module-template) repository for a fully functioning example of my current (and hopefully up to date) reference of this pattern.
"skipLibCheck": false, // See https://github.com/voxpelli/tsconfig/issues/1
9
+
"esModuleInterop": true, // Will be true anyhow because module is nodenext
10
+
"allowSyntheticDefaultImports": true, // Will be true anyhow because esModuleInterop is true
11
+
12
+
/* Node.js Module Setup */
13
+
"module": "nodenext", // Supports require() of ESM, see: https://www.typescriptlang.org/docs/handbook/modules/reference.html#node16-node18-nodenext
14
+
"moduleResolution": "nodenext", // Default when module is nodenext
15
+
16
+
"lib": ["esnext"], // Avoids DOM libraries etc being included
17
+
"target": "esnext", // Default when module is nodenext
18
+
19
+
"types": ["node"], // Avoids automatic inclusion of all visible ”@types” packages to be included
20
+
21
+
/* Clean up generated declarations */
22
+
"removeComments": true,
23
+
"stripInternal": true,
24
+
25
+
/* New checks being tried out */
26
+
"exactOptionalPropertyTypes": true,
27
+
"noFallthroughCasesInSwitch": true,
28
+
"noImplicitOverride": true,
29
+
"noPropertyAccessFromIndexSignature": true,
30
+
"noUncheckedIndexedAccess": true,
31
+
"noUncheckedSideEffectImports": true,
32
+
33
+
/* Additional checks */
34
+
"forceConsistentCasingInFileNames": true,
35
+
"noImplicitReturns": false, // Deactivated as I believe implicit "return undefined" at end of function is okay + explicit clashes with ESLint "no-useless-return"
36
+
"noUnusedLocals": true,
37
+
"noUnusedParameters": true
38
+
39
+
/* To make strict checking somewhat less strict during a transition stage, add one or more of: */
"esModuleInterop": true, // Will be true anyhow because module is node16
12
-
"allowSyntheticDefaultImports": true, // Will be true anyhow because esModuleInterop is true
13
-
"skipLibCheck": false, // See https://github.com/voxpelli/tsconfig/issues/1
14
-
"types": ["node"], // Don't implicitly pull in declarations from `@types` packages
15
-
16
-
/* Clean up generated declarations */
17
-
"removeComments": true,
18
-
"stripInternal": true,
19
-
20
-
/* Make it a JS-targeted config */
21
-
"allowJs": true,
22
-
"checkJs": true,
23
-
"noEmit": true,
24
-
"resolveJsonModule": true,
25
-
26
-
/* New checks being tried out */
27
-
"exactOptionalPropertyTypes": true,
28
-
"noFallthroughCasesInSwitch": true,
29
-
"noImplicitOverride": true,
30
-
"noPropertyAccessFromIndexSignature": true,
31
-
"noUncheckedIndexedAccess": true,
32
-
"noUncheckedSideEffectImports": true,
33
-
34
-
/* Additional checks */
35
-
"forceConsistentCasingInFileNames": true,
36
-
"noImplicitReturns": false, // Deactivated as I believe implicit "return undefined" at end of function is okay + explicit clashes with ESLint "no-useless-return"
37
-
"noUnusedLocals": true,
38
-
"noUnusedParameters": true
39
-
40
-
/* To make strict checking somewhat less strict during a transition stage, add one or more of: */
0 commit comments