eslint-config-typed 7.4.0 → 7.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -8
- package/dist/configs/nodejs.d.mts +14 -1
- package/dist/configs/nodejs.d.mts.map +1 -1
- package/dist/configs/nodejs.mjs +37 -4
- package/dist/configs/nodejs.mjs.map +1 -1
- package/dist/plugins/immer-coding-style/rules/prefer-curried-produce.d.mts +17 -3
- package/dist/plugins/immer-coding-style/rules/prefer-curried-produce.d.mts.map +1 -1
- package/dist/plugins/immer-coding-style/rules/prefer-curried-produce.mjs +124 -40
- package/dist/plugins/immer-coding-style/rules/prefer-curried-produce.mjs.map +1 -1
- package/dist/plugins/total-functions/rules/no-hidden-type-assertions.d.mts.map +1 -1
- package/dist/plugins/total-functions/rules/no-hidden-type-assertions.mjs +52 -61
- package/dist/plugins/total-functions/rules/no-hidden-type-assertions.mjs.map +1 -1
- package/dist/plugins/ts-restrictions/rules/no-export-type-side-effects.d.mts +23 -0
- package/dist/plugins/ts-restrictions/rules/no-export-type-side-effects.d.mts.map +1 -0
- package/dist/plugins/ts-restrictions/rules/no-export-type-side-effects.mjs +78 -0
- package/dist/plugins/ts-restrictions/rules/no-export-type-side-effects.mjs.map +1 -0
- package/dist/plugins/ts-restrictions/rules/no-ragged-comment-wrap.d.mts +12 -9
- package/dist/plugins/ts-restrictions/rules/no-ragged-comment-wrap.d.mts.map +1 -1
- package/dist/plugins/ts-restrictions/rules/no-ragged-comment-wrap.mjs +106 -17
- package/dist/plugins/ts-restrictions/rules/no-ragged-comment-wrap.mjs.map +1 -1
- package/dist/plugins/ts-restrictions/rules/require-ime-guard-on-enter.d.mts +49 -0
- package/dist/plugins/ts-restrictions/rules/require-ime-guard-on-enter.d.mts.map +1 -0
- package/dist/plugins/ts-restrictions/rules/require-ime-guard-on-enter.mjs +235 -0
- package/dist/plugins/ts-restrictions/rules/require-ime-guard-on-enter.mjs.map +1 -0
- package/dist/plugins/ts-restrictions/rules/rules.d.mts +4 -0
- package/dist/plugins/ts-restrictions/rules/rules.d.mts.map +1 -1
- package/dist/plugins/ts-restrictions/rules/rules.mjs +4 -0
- package/dist/plugins/ts-restrictions/rules/rules.mjs.map +1 -1
- package/dist/plugins/vitest-coding-style/rules/no-expect-to-strict-equal.d.mts +3 -1
- package/dist/plugins/vitest-coding-style/rules/no-expect-to-strict-equal.d.mts.map +1 -1
- package/dist/plugins/vitest-coding-style/rules/no-expect-to-strict-equal.mjs +11 -12
- package/dist/plugins/vitest-coding-style/rules/no-expect-to-strict-equal.mjs.map +1 -1
- package/dist/plugins/vitest-coding-style/rules/prefer-assert-is-false-over-expect-false.d.mts +2 -1
- package/dist/plugins/vitest-coding-style/rules/prefer-assert-is-false-over-expect-false.d.mts.map +1 -1
- package/dist/plugins/vitest-coding-style/rules/prefer-assert-is-false-over-expect-false.mjs +36 -24
- package/dist/plugins/vitest-coding-style/rules/prefer-assert-is-false-over-expect-false.mjs.map +1 -1
- package/dist/plugins/vitest-coding-style/rules/prefer-assert-is-true-over-expect-true.d.mts +2 -1
- package/dist/plugins/vitest-coding-style/rules/prefer-assert-is-true-over-expect-true.d.mts.map +1 -1
- package/dist/plugins/vitest-coding-style/rules/prefer-assert-is-true-over-expect-true.mjs +36 -24
- package/dist/plugins/vitest-coding-style/rules/prefer-assert-is-true-over-expect-true.mjs.map +1 -1
- package/dist/plugins/vitest-coding-style/rules/vitest-binding.d.mts +25 -0
- package/dist/plugins/vitest-coding-style/rules/vitest-binding.d.mts.map +1 -1
- package/dist/plugins/vitest-coding-style/rules/vitest-binding.mjs +56 -1
- package/dist/plugins/vitest-coding-style/rules/vitest-binding.mjs.map +1 -1
- package/dist/rules/eslint-rules.d.mts +97 -8
- package/dist/rules/eslint-rules.d.mts.map +1 -1
- package/dist/rules/eslint-rules.mjs +29 -3
- package/dist/rules/eslint-rules.mjs.map +1 -1
- package/dist/rules/eslint-ts-restrictions-rules.d.mts +2 -0
- package/dist/rules/eslint-ts-restrictions-rules.d.mts.map +1 -1
- package/dist/rules/eslint-ts-restrictions-rules.mjs +2 -0
- package/dist/rules/eslint-ts-restrictions-rules.mjs.map +1 -1
- package/dist/rules/eslint-unicorn-rules.d.mts +57 -12
- package/dist/rules/eslint-unicorn-rules.d.mts.map +1 -1
- package/dist/rules/eslint-unicorn-rules.mjs +56 -10
- package/dist/rules/eslint-unicorn-rules.mjs.map +1 -1
- package/dist/rules/index.d.mts +1 -0
- package/dist/rules/index.d.mts.map +1 -1
- package/dist/rules/index.mjs +1 -0
- package/dist/rules/index.mjs.map +1 -1
- package/dist/rules/node-version-gated-apis.d.mts +108 -0
- package/dist/rules/node-version-gated-apis.d.mts.map +1 -0
- package/dist/rules/node-version-gated-apis.mjs +226 -0
- package/dist/rules/node-version-gated-apis.mjs.map +1 -0
- package/dist/rules/typescript-eslint-rules.d.mts.map +1 -1
- package/dist/rules/typescript-eslint-rules.mjs +4 -0
- package/dist/rules/typescript-eslint-rules.mjs.map +1 -1
- package/dist/types/rules/eslint-ts-restrictions-rules.d.mts +59 -2
- package/dist/types/rules/eslint-ts-restrictions-rules.d.mts.map +1 -1
- package/package.json +13 -12
- package/src/configs/nodejs.mts +63 -4
- package/src/configs/nodejs.test.mts +83 -0
- package/src/configs/typescript.test.mts +232 -23
- package/src/plugins/immer-coding-style/rules/prefer-curried-produce.mts +207 -63
- package/src/plugins/immer-coding-style/rules/prefer-curried-produce.test.mts +316 -10
- package/src/plugins/total-functions/rules/no-hidden-type-assertions.mts +127 -139
- package/src/plugins/total-functions/rules/no-hidden-type-assertions.test.mts +139 -0
- package/src/plugins/ts-restrictions/rules/no-export-type-side-effects.mts +102 -0
- package/src/plugins/ts-restrictions/rules/no-export-type-side-effects.test.mts +129 -0
- package/src/plugins/ts-restrictions/rules/no-ragged-comment-wrap.mts +176 -35
- package/src/plugins/ts-restrictions/rules/no-ragged-comment-wrap.test.mts +305 -1
- package/src/plugins/ts-restrictions/rules/require-ime-guard-on-enter.mts +333 -0
- package/src/plugins/ts-restrictions/rules/require-ime-guard-on-enter.test.mts +498 -0
- package/src/plugins/ts-restrictions/rules/rules.mts +4 -0
- package/src/plugins/vitest-coding-style/rules/no-expect-to-strict-equal.mts +27 -21
- package/src/plugins/vitest-coding-style/rules/no-expect-to-strict-equal.test.mts +115 -0
- package/src/plugins/vitest-coding-style/rules/prefer-assert-coding-style-rules.test.mts +330 -0
- package/src/plugins/vitest-coding-style/rules/prefer-assert-is-false-over-expect-false.mts +58 -31
- package/src/plugins/vitest-coding-style/rules/prefer-assert-is-true-over-expect-true.mts +58 -31
- package/src/plugins/vitest-coding-style/rules/vitest-binding.mts +89 -1
- package/src/rules/eslint-rules.mts +37 -3
- package/src/rules/eslint-ts-restrictions-rules.mts +2 -0
- package/src/rules/eslint-unicorn-rules.mts +58 -12
- package/src/rules/index.mts +1 -0
- package/src/rules/node-version-gated-apis.mts +289 -0
- package/src/rules/node-version-gated-apis.test.mts +92 -0
- package/src/rules/typescript-eslint-rules.mts +5 -1
- package/src/types/rules/eslint-ts-restrictions-rules.mts +65 -2
package/README.md
CHANGED
|
@@ -367,6 +367,15 @@ export default [
|
|
|
367
367
|
] satisfies readonly FlatConfig[];
|
|
368
368
|
```
|
|
369
369
|
|
|
370
|
+
The presets report the built-in APIs, globals and syntax that the oldest
|
|
371
|
+
Node.js in this package's `engines.node` lacks (`Temporal`, `Iterator.zip`,
|
|
372
|
+
`using`, …), and turn off the rules whose fixes would write them. Files that run
|
|
373
|
+
only on a known newer Node.js, such as a repository's own scripts, pass its
|
|
374
|
+
major: `eslintConfigForNodeJs(['scripts/**'], { nodeMajor: 26 })` allows what
|
|
375
|
+
Node.js 26 has and still reports what it lacks. With `nodeMajor` the preset sets
|
|
376
|
+
the options of `no-restricted-globals`, `no-restricted-properties` and
|
|
377
|
+
`no-restricted-syntax` for those files, replacing any set before it.
|
|
378
|
+
|
|
370
379
|
### Node.js TypeScript Project
|
|
371
380
|
|
|
372
381
|
```tsx
|
|
@@ -538,13 +547,14 @@ Pre-configured rule sets that can be imported and customized:
|
|
|
538
547
|
|
|
539
548
|
### Exported Pre-configured Rule Options
|
|
540
549
|
|
|
541
|
-
| Pre-configured rule option | Rule
|
|
542
|
-
| :-------------------------------------- |
|
|
543
|
-
| **`restrictedGlobals`** | `no-restricted-globals`
|
|
544
|
-
| **`restrictedGlobalsForBrowser`** | `no-restricted-globals`
|
|
545
|
-
| **`restrictedSyntax`** | `no-restricted-syntax`
|
|
546
|
-
| **`
|
|
547
|
-
| **`
|
|
550
|
+
| Pre-configured rule option | Rule | Description |
|
|
551
|
+
| :-------------------------------------- | :------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
552
|
+
| **`restrictedGlobals`** | `no-restricted-globals` | Array of restricted global variables |
|
|
553
|
+
| **`restrictedGlobalsForBrowser`** | `no-restricted-globals` | Browser-environment-specific restricted globals |
|
|
554
|
+
| **`restrictedSyntax`** | `no-restricted-syntax` | Disallows the `in` operator, `Object.prototype.hasOwnProperty.call` (suggests using `Object.hasOwn`), `new Array(*)` syntax (suggests using `Array.from`), and the `globalThis.`-qualified forms of the APIs `restrictedProperties` disallows |
|
|
555
|
+
| **`restrictedProperties`** | `no-restricted-properties` | Disallows the built-in APIs in `nodeVersionGatedApis`, which not every Node.js in `engines` has: `Error.isError`, `Promise.try`, `RegExp.escape`, `Uint8Array` base64 and `Map#getOrInsert[Computed]` |
|
|
556
|
+
| **`restrictedImportsOptions`** | `no-restricted-imports` | Disallows importing `index.mjs` by relative path |
|
|
557
|
+
| **`restrictedImportsOptionsForPreact`** | `no-restricted-imports` | `restrictedImportsOptions` plus the hooks of `preact/compat` (suggests `preact/hooks`) |
|
|
548
558
|
|
|
549
559
|
A config that sets a rule replaces the options an earlier config set. To restrict more imports after `eslintConfigForPreact`, concatenate yours with the ones it set, using `mergeRestrictedImportsOptions(restrictedImportsOptionsForPreact, { paths: [...], patterns: [...] })`.
|
|
550
560
|
|
|
@@ -570,7 +580,7 @@ The shape of the rule option varies depending on the rule, so please check the c
|
|
|
570
580
|
|
|
571
581
|
**`eslintPluginTsRestrictions`** - Custom ESLint plugin with additional rules for TypeScript
|
|
572
582
|
|
|
573
|
-
-
|
|
583
|
+
- Provides the `ts-restrictions/*` rules; `eslintTsRestrictionsRules` lists each one with the severity the preset sets. `ts-restrictions/no-restricted-syntax` duplicates ESLint's `no-restricted-syntax` rule.
|
|
574
584
|
- Can be used to set the error level to `error` or `warn` as needed.
|
|
575
585
|
|
|
576
586
|
Example:
|
|
@@ -1,3 +1,16 @@
|
|
|
1
1
|
import { type FlatConfig } from '../types/index.mjs';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* The Node.js globals and rules for `files`.
|
|
4
|
+
*
|
|
5
|
+
* `nodeMajor` is for files that run only on a known Node.js, newer than this
|
|
6
|
+
* package's `engines.node` floor — a repository's own scripts, say. The APIs,
|
|
7
|
+
* globals and syntax that the floor lacks and that runtime has are then
|
|
8
|
+
* allowed (`nodeVersionGateAt`); without it, every one the floor lacks is
|
|
9
|
+
* reported. With it, the preset sets the options of `no-restricted-globals`,
|
|
10
|
+
* `no-restricted-properties` and `no-restricted-syntax` for `files`, replacing
|
|
11
|
+
* any set before it there, as a flat config does.
|
|
12
|
+
*/
|
|
13
|
+
export declare const eslintConfigForNodeJs: (files?: readonly string[], options?: Readonly<{
|
|
14
|
+
nodeMajor?: number;
|
|
15
|
+
}>) => FlatConfig;
|
|
3
16
|
//# sourceMappingURL=nodejs.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodejs.d.mts","sourceRoot":"","sources":["../../src/configs/nodejs.mts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"nodejs.d.mts","sourceRoot":"","sources":["../../src/configs/nodejs.mts"],"names":[],"mappings":"AAQA,OAAO,EAIL,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,WACxB,SAAS,MAAM,EAAE,YACf,QAAQ,CAAC;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,KACzC,UAmDU,CAAC"}
|
package/dist/configs/nodejs.mjs
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import globals from 'globals';
|
|
2
2
|
import { Arr } from 'ts-data-forge';
|
|
3
|
-
import { restrictedGlobals } from '../rules/index.mjs';
|
|
4
|
-
import { defineKnownRules } from '../types/index.mjs';
|
|
5
|
-
|
|
3
|
+
import { nodeVersionGateAt, restrictedGlobals, restrictedGlobalsWithoutNodeVersionGate, restrictedSyntaxWithoutNodeVersionGate, } from '../rules/index.mjs';
|
|
4
|
+
import { defineKnownRules, } from '../types/index.mjs';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export const eslintConfigForNodeJs = (files, options) => ({
|
|
6
17
|
...(files === undefined ? {} : { files }),
|
|
7
18
|
languageOptions: {
|
|
8
19
|
|
|
@@ -11,7 +22,11 @@ export const eslintConfigForNodeJs = (files) => ({
|
|
|
11
22
|
},
|
|
12
23
|
},
|
|
13
24
|
rules: defineKnownRules({
|
|
14
|
-
|
|
25
|
+
...(options?.nodeMajor === undefined
|
|
26
|
+
? {
|
|
27
|
+
'no-restricted-globals': Arr.toUnshifted('error')(restrictedGlobals),
|
|
28
|
+
}
|
|
29
|
+
: runtimeGate(options.nodeMajor)),
|
|
15
30
|
'no-alert': 'off',
|
|
16
31
|
'no-implicit-globals': 'off',
|
|
17
32
|
'no-script-url': 'off',
|
|
@@ -47,4 +62,22 @@ export const eslintConfigForNodeJs = (files) => ({
|
|
|
47
62
|
'unicorn/require-passive-events': 'off',
|
|
48
63
|
}),
|
|
49
64
|
});
|
|
65
|
+
|
|
66
|
+
const runtimeGate = (nodeMajor) => {
|
|
67
|
+
const gate = nodeVersionGateAt(nodeMajor);
|
|
68
|
+
const globalsOption = [
|
|
69
|
+
...restrictedGlobalsWithoutNodeVersionGate,
|
|
70
|
+
...gate.globals,
|
|
71
|
+
];
|
|
72
|
+
const propertiesOption = gate.properties;
|
|
73
|
+
const syntaxOption = [
|
|
74
|
+
...restrictedSyntaxWithoutNodeVersionGate,
|
|
75
|
+
...gate.syntax,
|
|
76
|
+
];
|
|
77
|
+
return {
|
|
78
|
+
'no-restricted-globals': Arr.toUnshifted('error')(globalsOption),
|
|
79
|
+
'no-restricted-properties': Arr.toUnshifted('error')(propertiesOption),
|
|
80
|
+
'no-restricted-syntax': Arr.toUnshifted('error')(syntaxOption),
|
|
81
|
+
};
|
|
82
|
+
};
|
|
50
83
|
//# sourceMappingURL=nodejs.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodejs.mjs","sourceRoot":"","sources":["../../src/configs/nodejs.mts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACpC,OAAO,
|
|
1
|
+
{"version":3,"file":"nodejs.mjs","sourceRoot":"","sources":["../../src/configs/nodejs.mts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACpC,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,uCAAuC,EACvC,sCAAsC,GACvC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,GAIjB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,KAAyB,EACzB,OAA0C,EAC9B,EAAE,CACd,CAAC;IACC,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;IACzC,eAAe,EAAE;QACf,iEAAiE;QACjE,OAAO,EAAE;YACP,GAAG,OAAO,CAAC,IAAI;SAChB;KACF;IACD,KAAK,EAAE,gBAAgB,CAAC;QACtB,GAAG,CAAC,OAAO,EAAE,SAAS,KAAK,SAAS;YAClC,CAAC,CAAC;gBACE,uBAAuB,EACrB,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,iBAAiB,CAAC;aAC9C;YACH,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACnC,UAAU,EAAE,KAAK;QACjB,qBAAqB,EAAE,KAAK;QAC5B,eAAe,EAAE,KAAK;QAEtB,4BAA4B,EAAE,KAAK;QACnC,kCAAkC,EAAE,KAAK;QACzC,0CAA0C,EAAE,KAAK;QACjD,qCAAqC,EAAE,KAAK;QAC5C,iCAAiC,EAAE,KAAK;QACxC,gCAAgC,EAAE,KAAK;QACvC,0BAA0B,EAAE,KAAK;QACjC,gCAAgC,EAAE,KAAK;QACvC,sCAAsC,EAAE,KAAK;QAC7C,6BAA6B,EAAE,KAAK;QACpC,mCAAmC,EAAE,KAAK;QAC1C,gCAAgC,EAAE,KAAK;QACvC,+BAA+B,EAAE,KAAK;QACtC,4CAA4C,EAAE,KAAK;QACnD,mCAAmC,EAAE,KAAK;QAC1C,+BAA+B,EAAE,KAAK;QACtC,yBAAyB,EAAE,KAAK;QAChC,4BAA4B,EAAE,KAAK;QACnC,qCAAqC,EAAE,KAAK;QAC5C,sCAAsC,EAAE,KAAK;QAC7C,uCAAuC,EAAE,KAAK;QAC9C,4BAA4B,EAAE,KAAK;QACnC,2CAA2C,EAAE,KAAK;QAClD,sCAAsC,EAAE,KAAK;QAC7C,gCAAgC,EAAE,KAAK;QACvC,uBAAuB,EAAE,KAAK;QAC9B,gCAAgC,EAAE,KAAK;QACvC,qCAAqC,EAAE,KAAK;QAC5C,4BAA4B,EAAE,KAAK;QACnC,gCAAgC,EAAE,KAAK;KACxC,CAAC;CACH,CAAU,CAAC;AAEd,6DAA6D;AAC7D,MAAM,WAAW,GAAG,CAClB,SAAiB,EAKhB,EAAE;IACH,MAAM,IAAI,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAE1C,MAAM,aAAa,GAA+C;QAChE,GAAG,uCAAuC;QAC1C,GAAG,IAAI,CAAC,OAAO;KACP,CAAC;IAEX,MAAM,gBAAgB,GACpB,IAAI,CAAC,UAAU,CAAC;IAElB,MAAM,YAAY,GAA8C;QAC9D,GAAG,sCAAsC;QACzC,GAAG,IAAI,CAAC,MAAM;KACN,CAAC;IAEX,OAAO;QACL,uBAAuB,EAAE,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC;QAChE,0BAA0B,EAAE,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,gBAAgB,CAAC;QACtE,sBAAsB,EAAE,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC;KAC/D,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -3,8 +3,9 @@ type MessageIds = 'useCurriedProduce';
|
|
|
3
3
|
/**
|
|
4
4
|
* Rewrites `(state) => produce(state, recipe)` as `produce(recipe)`. The base
|
|
5
5
|
* state is recognized through type wrappers (`produce(state satisfies State,
|
|
6
|
-
* recipe)`), which change nothing at run time and go with the argument
|
|
7
|
-
* type
|
|
6
|
+
* recipe)`), which change nothing at run time and go with the argument. The
|
|
7
|
+
* type argument is the call's own (`produce<State>(state, recipe)`), else the
|
|
8
|
+
* parameter's annotation, else the wrapper's return type.
|
|
8
9
|
*
|
|
9
10
|
* The curried form passes its extra arguments on to the recipe (`recipe(draft,
|
|
10
11
|
* ...args)`), so `xs.map((s) => produce(s, r))` → `xs.map(produce(r))` would
|
|
@@ -19,7 +20,20 @@ type MessageIds = 'useCurriedProduce';
|
|
|
19
20
|
* would have nowhere to declare, and so is a base under `!`
|
|
20
21
|
* (`produce(state!, recipe)`): the curried form would take the draft's narrower
|
|
21
22
|
* type, and its callers could no longer pass what the wrapper took.
|
|
22
|
-
* An optional parameter is left alone for the same reason
|
|
23
|
+
* An optional parameter is left alone for the same reason, and so is a base
|
|
24
|
+
* under an `as` or `<T>` whose type is not the parameter's annotation
|
|
25
|
+
* (`(state: State | undefined) => produce(state as State, recipe)`), or that
|
|
26
|
+
* casts an unannotated parameter, whose type may come from the context.
|
|
27
|
+
* A call under `as` or `<T>` (`produce(state, recipe) as View`) is left alone
|
|
28
|
+
* too, since no curried form returns the type it asserts.
|
|
29
|
+
*
|
|
30
|
+
* `produce` is immer's: a named, aliased, default or namespace import from
|
|
31
|
+
* `immer` that nothing nearer shadows. The call and its callee are read through
|
|
32
|
+
* type wrappers. A call under `satisfies` or `!`, and a callee or namespace
|
|
33
|
+
* object in any wrapper (`(produce as typeof produce)(state, recipe)`,
|
|
34
|
+
* `(immer as T).produce(…)`), are reported without a fix, which could not keep
|
|
35
|
+
* the wrapper; so is an updater with a comment outside the recipe, which the
|
|
36
|
+
* fix would delete.
|
|
23
37
|
*/
|
|
24
38
|
export declare const preferCurriedProduceRule: TSESLint.RuleModule<MessageIds>;
|
|
25
39
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-curried-produce.d.mts","sourceRoot":"","sources":["../../../../src/plugins/immer-coding-style/rules/prefer-curried-produce.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"prefer-curried-produce.d.mts","sourceRoot":"","sources":["../../../../src/plugins/immer-coding-style/rules/prefer-curried-produce.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAalC,KAAK,UAAU,GAAG,mBAAmB,CAAC;AAOtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,CAuL3D,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
|
|
2
|
-
import { isTypeWrapper, skipTypeWrappers, typeWrapperLayers, } from 'eslint-rule-forge';
|
|
2
|
+
import { buildCalleeResolver, getImportDeclarations, hasCommentWithin, hasForeignBinding, isTypeWrapper, skipTypeWrappers, typeWrapperLayers, } from 'eslint-rule-forge';
|
|
3
3
|
import { Arr, hasKey, isRecord } from 'ts-data-forge';
|
|
4
4
|
|
|
5
5
|
|
|
@@ -15,6 +15,20 @@ import { Arr, hasKey, isRecord } from 'ts-data-forge';
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
18
32
|
|
|
19
33
|
|
|
20
34
|
|
|
@@ -37,6 +51,35 @@ export const preferCurriedProduceRule = {
|
|
|
37
51
|
},
|
|
38
52
|
create: (context) => {
|
|
39
53
|
const sourceCode = context.sourceCode;
|
|
54
|
+
const immerImports = getImportDeclarations(sourceCode.ast, immerModule);
|
|
55
|
+
if (Arr.isEmpty(immerImports)) {
|
|
56
|
+
return {};
|
|
57
|
+
}
|
|
58
|
+
const resolveCallee = buildCalleeResolver(immerImports);
|
|
59
|
+
|
|
60
|
+
const defaultImportNames = new Set(immerImports.flatMap((declaration) => Arr.generate(function* () {
|
|
61
|
+
for (const specifier of declaration.specifiers) {
|
|
62
|
+
if (specifier.type === AST_NODE_TYPES.ImportDefaultSpecifier) {
|
|
63
|
+
yield specifier.local.name;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
})));
|
|
67
|
+
const isImmerProduce = (call) => {
|
|
68
|
+
const callee = call.callee;
|
|
69
|
+
const canonicalName = resolveCallee(callee)?.canonicalName;
|
|
70
|
+
const unwrapped = skipTypeWrappers(callee);
|
|
71
|
+
if (canonicalName !== 'produce' &&
|
|
72
|
+
canonicalName !== 'default' &&
|
|
73
|
+
!(unwrapped.type === AST_NODE_TYPES.Identifier &&
|
|
74
|
+
defaultImportNames.has(unwrapped.name))) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
const bound = unwrapped.type === AST_NODE_TYPES.MemberExpression
|
|
78
|
+
? skipTypeWrappers(unwrapped.object)
|
|
79
|
+
: unwrapped;
|
|
80
|
+
return (bound.type === AST_NODE_TYPES.Identifier &&
|
|
81
|
+
!hasForeignBinding(sourceCode, call, bound.name, immerModule));
|
|
82
|
+
};
|
|
40
83
|
return {
|
|
41
84
|
ArrowFunctionExpression: (node) => {
|
|
42
85
|
if (node.async ||
|
|
@@ -53,8 +96,12 @@ export const preferCurriedProduceRule = {
|
|
|
53
96
|
return;
|
|
54
97
|
}
|
|
55
98
|
const { name: parameterName } = param;
|
|
56
|
-
const callExpression = node.body;
|
|
57
|
-
|
|
99
|
+
const callExpression = skipTypeWrappers(node.body);
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
if (callExpression.type !== AST_NODE_TYPES.CallExpression ||
|
|
103
|
+
!isImmerProduce(callExpression) ||
|
|
104
|
+
typeWrapperLayers(node.body).some((layer) => castTypeOf(layer) !== undefined)) {
|
|
58
105
|
return;
|
|
59
106
|
}
|
|
60
107
|
const [baseArgument, ...restArguments] = callExpression.arguments;
|
|
@@ -68,6 +115,14 @@ export const preferCurriedProduceRule = {
|
|
|
68
115
|
if (typeWrapperLayers(baseArgument).some((layer) => layer.type === AST_NODE_TYPES.TSNonNullExpression)) {
|
|
69
116
|
return;
|
|
70
117
|
}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
if (assertsOtherType(baseArgument, param.typeAnnotation === undefined
|
|
122
|
+
? undefined
|
|
123
|
+
: tokensText(sourceCode, param.typeAnnotation.typeAnnotation), sourceCode)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
71
126
|
const baseIdentifier = findIdentifier(baseArgument, parameterName);
|
|
72
127
|
if (baseIdentifier === undefined) {
|
|
73
128
|
return;
|
|
@@ -75,10 +130,17 @@ export const preferCurriedProduceRule = {
|
|
|
75
130
|
if (hasOtherReferences(context, parameterName, baseIdentifier)) {
|
|
76
131
|
return;
|
|
77
132
|
}
|
|
133
|
+
const recipe = restArguments[0];
|
|
134
|
+
const isFixable = node.body === callExpression &&
|
|
135
|
+
!hasWrappedCallee(callExpression) &&
|
|
136
|
+
!hasCommentWithin(sourceCode, node, [
|
|
137
|
+
[node.range[0], recipe.range[0]],
|
|
138
|
+
[recipe.range[1], node.range[1]],
|
|
139
|
+
]);
|
|
78
140
|
report(context, {
|
|
79
141
|
arrowFunction: node,
|
|
80
|
-
baseArgument,
|
|
81
142
|
callExpression,
|
|
143
|
+
isFixable,
|
|
82
144
|
remainingArguments: restArguments,
|
|
83
145
|
sourceCode,
|
|
84
146
|
});
|
|
@@ -97,17 +159,6 @@ const getTypeArguments = (node) => {
|
|
|
97
159
|
}
|
|
98
160
|
return undefined;
|
|
99
161
|
};
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const getAssertedType = (node) => {
|
|
105
|
-
if (node.type === AST_NODE_TYPES.TSAsExpression ||
|
|
106
|
-
node.type === AST_NODE_TYPES.TSTypeAssertion) {
|
|
107
|
-
return node.typeAnnotation;
|
|
108
|
-
}
|
|
109
|
-
return isTypeWrapper(node) ? getAssertedType(node.expression) : undefined;
|
|
110
|
-
};
|
|
111
162
|
const getArrowFunctionParameterType = ({ arrowFunction, sourceCode, }) => {
|
|
112
163
|
const [parameter] = arrowFunction.params;
|
|
113
164
|
if (parameter?.type !== AST_NODE_TYPES.Identifier) {
|
|
@@ -124,16 +175,13 @@ const getArrowFunctionReturnType = ({ arrowFunction, sourceCode, }) => {
|
|
|
124
175
|
? undefined
|
|
125
176
|
: sourceCode.getText(typeAnnotation);
|
|
126
177
|
};
|
|
127
|
-
const getTypeParametersText = ({ arrowFunction,
|
|
178
|
+
const getTypeParametersText = ({ arrowFunction, callExpression, sourceCode, }) => {
|
|
128
179
|
const typeArguments = getTypeArguments(callExpression);
|
|
129
180
|
if (typeArguments !== undefined) {
|
|
130
181
|
return sourceCode.getText(typeArguments);
|
|
131
182
|
}
|
|
132
183
|
|
|
133
|
-
|
|
134
|
-
if (assertedType !== undefined) {
|
|
135
|
-
return `<${sourceCode.getText(assertedType)}>`;
|
|
136
|
-
}
|
|
184
|
+
|
|
137
185
|
const parameterType = getArrowFunctionParameterType({
|
|
138
186
|
arrowFunction,
|
|
139
187
|
sourceCode,
|
|
@@ -165,31 +213,67 @@ const normalizeMultilineText = (text) => {
|
|
|
165
213
|
const normalized = lines.map((line, index) => index === 0 ? line : line.slice(minIndent));
|
|
166
214
|
return normalized.join('\n');
|
|
167
215
|
};
|
|
168
|
-
const report = (context, { arrowFunction,
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
216
|
+
const report = (context, { arrowFunction, callExpression, isFixable, remainingArguments, sourceCode, }) => {
|
|
217
|
+
const buildReplacement = () => {
|
|
218
|
+
const calleeText = sourceCode.getText(callExpression.callee);
|
|
219
|
+
const typeParametersText = getTypeParametersText({
|
|
220
|
+
arrowFunction,
|
|
221
|
+
callExpression,
|
|
222
|
+
sourceCode,
|
|
223
|
+
});
|
|
224
|
+
const remainingArgumentsText = remainingArguments
|
|
225
|
+
.map((argument) => normalizeMultilineText(sourceCode.getText(argument)))
|
|
226
|
+
.join(', ');
|
|
227
|
+
return `${calleeText}${typeParametersText}(${remainingArgumentsText})`;
|
|
228
|
+
};
|
|
180
229
|
context.report({
|
|
181
230
|
node: arrowFunction,
|
|
182
231
|
messageId: 'useCurriedProduce',
|
|
183
|
-
fix:
|
|
232
|
+
fix: isFixable
|
|
233
|
+
? (fixer) => fixer.replaceText(arrowFunction, buildReplacement())
|
|
234
|
+
: null,
|
|
184
235
|
});
|
|
185
236
|
};
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
237
|
+
const immerModule = 'immer';
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
const castTypeOf = (node) => node.type === AST_NODE_TYPES.TSAsExpression ||
|
|
243
|
+
node.type === AST_NODE_TYPES.TSTypeAssertion
|
|
244
|
+
? node.typeAnnotation
|
|
245
|
+
: undefined;
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
const hasWrappedCallee = ({ callee, }) => isTypeWrapper(callee) ||
|
|
252
|
+
(callee.type === AST_NODE_TYPES.MemberExpression &&
|
|
253
|
+
isTypeWrapper(callee.object));
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
const tokensText = (sourceCode,
|
|
259
|
+
|
|
260
|
+
node) => sourceCode
|
|
261
|
+
.getTokens(node)
|
|
262
|
+
.map((token) => token.value)
|
|
263
|
+
.join(' ');
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
const assertsOtherType = (argument, parameterType, sourceCode) => argument.type !== AST_NODE_TYPES.SpreadElement &&
|
|
272
|
+
typeWrapperLayers(argument).some((layer) => {
|
|
273
|
+
const castType = castTypeOf(layer);
|
|
274
|
+
return (castType !== undefined &&
|
|
275
|
+
tokensText(sourceCode, castType) !== parameterType);
|
|
276
|
+
});
|
|
193
277
|
|
|
194
278
|
|
|
195
279
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-curried-produce.mjs","sourceRoot":"","sources":["../../../../src/plugins/immer-coding-style/rules/prefer-curried-produce.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,GAGf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAUvE
|
|
1
|
+
{"version":3,"file":"prefer-curried-produce.mjs","sourceRoot":"","sources":["../../../../src/plugins/immer-coding-style/rules/prefer-curried-produce.mts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-hidden-type-assertions.d.mts","sourceRoot":"","sources":["../../../../src/plugins/total-functions/rules/no-hidden-type-assertions.mts"],"names":[],"mappings":"AAIA,OAAO,EAEL,WAAW,EAEZ,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"no-hidden-type-assertions.d.mts","sourceRoot":"","sources":["../../../../src/plugins/total-functions/rules/no-hidden-type-assertions.mts"],"names":[],"mappings":"AAIA,OAAO,EAEL,WAAW,EAEZ,MAAM,0BAA0B,CAAC;AAmBlC,oDAAoD;AAEpD,eAAO,MAAM,sBAAsB;;CAoRxB,CAAC"}
|
|
@@ -2,7 +2,7 @@ import { isTypeNeverType, isTypeUnknownType, } from '@typescript-eslint/type-uti
|
|
|
2
2
|
import { AST_NODE_TYPES, ESLintUtils, } from '@typescript-eslint/utils';
|
|
3
3
|
import { typeWrapperLayers } from 'eslint-rule-forge';
|
|
4
4
|
import { Arr } from 'ts-data-forge';
|
|
5
|
-
import {
|
|
5
|
+
import { forEachChild, isIdentifier, isMappedTypeNode, isTypeParameterDeclaration, isTypeReferenceNode, SyntaxKind, } from 'typescript';
|
|
6
6
|
import { createRule } from './common.mjs';
|
|
7
7
|
|
|
8
8
|
export const noHiddenTypeAssertions = createRule({
|
|
@@ -26,30 +26,20 @@ export const noHiddenTypeAssertions = createRule({
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
? type.members.flatMap((m) => hasTypeNode(m) ? [m.type] : [])
|
|
44
|
-
: isArrayTypeNode(type)
|
|
45
|
-
? [type.elementType]
|
|
46
|
-
: isTypeOperatorNode(type)
|
|
47
|
-
? [type.type]
|
|
48
|
-
: isUnionTypeNode(type) || isIntersectionTypeNode(type)
|
|
49
|
-
? type.types
|
|
50
|
-
: [];
|
|
51
|
-
return Arr.toUnshifted(type)(next.flatMap(explodeTypeNode));
|
|
52
|
-
};
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
const referencesTypeParameter = (node, typeParameter) => (!isTypeParameterDeclaration(node) || isMappedTypeNode(node.parent)) &&
|
|
37
|
+
((isTypeReferenceNode(node) &&
|
|
38
|
+
isIdentifier(node.typeName) &&
|
|
39
|
+
node.typeName.text === typeParameter.name &&
|
|
40
|
+
checker.getSymbolAtLocation(node.typeName) === typeParameter) ||
|
|
41
|
+
(forEachChild(node, (child) => referencesTypeParameter(child, typeParameter) || undefined) ??
|
|
42
|
+
false));
|
|
53
43
|
|
|
54
44
|
|
|
55
45
|
|
|
@@ -62,25 +52,42 @@ export const noHiddenTypeAssertions = createRule({
|
|
|
62
52
|
typeParameters.length === 0) {
|
|
63
53
|
return undefined;
|
|
64
54
|
}
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
55
|
+
const used = typeParameters.flatMap((typeParameter, index) => {
|
|
56
|
+
const symbol = checker.getSymbolAtLocation(typeParameter.name);
|
|
57
|
+
return symbol !== undefined &&
|
|
58
|
+
referencesTypeParameter(returnType, symbol)
|
|
59
|
+
? [{ typeParameter, symbol, index }]
|
|
60
|
+
: [];
|
|
61
|
+
});
|
|
62
|
+
return Arr.isNonEmpty(used) ? used : undefined;
|
|
71
63
|
};
|
|
72
64
|
|
|
73
65
|
|
|
74
66
|
|
|
75
67
|
|
|
76
68
|
|
|
77
|
-
const returnTypeParamsAppearInValueParams = (declaration, typeParamsUsedInReturnType) => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
69
|
+
const returnTypeParamsAppearInValueParams = (declaration, typeParamsUsedInReturnType) => typeParamsUsedInReturnType.every(({ symbol }) => declaration.parameters.some((parameter) => parameter.type !== undefined &&
|
|
70
|
+
referencesTypeParameter(parameter.type, symbol)));
|
|
71
|
+
const mut_analysisCache = new WeakMap();
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
const analyzeSignature = (declaration) => {
|
|
79
|
+
if (mut_analysisCache.has(declaration)) {
|
|
80
|
+
return mut_analysisCache.get(declaration);
|
|
81
|
+
}
|
|
82
|
+
const typeParamsUsedInReturnType = typeParamsUsedInReturnTypeOf(declaration);
|
|
83
|
+
const analysis = typeParamsUsedInReturnType === undefined
|
|
84
|
+
? undefined
|
|
85
|
+
: {
|
|
86
|
+
typeParamsUsedInReturnType,
|
|
87
|
+
appearInValueParams: returnTypeParamsAppearInValueParams(declaration, typeParamsUsedInReturnType),
|
|
88
|
+
};
|
|
89
|
+
mut_analysisCache.set(declaration, analysis);
|
|
90
|
+
return analysis;
|
|
84
91
|
};
|
|
85
92
|
|
|
86
93
|
|
|
@@ -92,9 +99,8 @@ export const noHiddenTypeAssertions = createRule({
|
|
|
92
99
|
declaration.kind === SyntaxKind.JSDocSignature) {
|
|
93
100
|
return false;
|
|
94
101
|
}
|
|
95
|
-
const
|
|
96
|
-
return
|
|
97
|
-
!returnTypeParamsAppearInValueParams(declaration, typeParamsUsedInReturnType));
|
|
102
|
+
const analysis = analyzeSignature(declaration);
|
|
103
|
+
return analysis !== undefined && !analysis.appearInValueParams;
|
|
98
104
|
});
|
|
99
105
|
|
|
100
106
|
|
|
@@ -142,14 +148,15 @@ export const noHiddenTypeAssertions = createRule({
|
|
|
142
148
|
|
|
143
149
|
return;
|
|
144
150
|
}
|
|
145
|
-
const
|
|
146
|
-
if (
|
|
151
|
+
const analysis = analyzeSignature(callSignature.declaration);
|
|
152
|
+
if (analysis === undefined) {
|
|
147
153
|
return;
|
|
148
154
|
}
|
|
149
155
|
|
|
150
156
|
|
|
151
157
|
|
|
152
|
-
|
|
158
|
+
|
|
159
|
+
const allCorrespondingTypeArgumentsAreUnknownType = analysis.typeParamsUsedInReturnType.every(({ index, typeParameter }) => {
|
|
153
160
|
const typeArgument = (tsExpressionNode.typeArguments ?? [])[index];
|
|
154
161
|
const typeArgumentType = typeArgument !== undefined
|
|
155
162
|
? checker.getTypeAtLocation(typeArgument)
|
|
@@ -164,7 +171,7 @@ export const noHiddenTypeAssertions = createRule({
|
|
|
164
171
|
if (allCorrespondingTypeArgumentsAreUnknownType) {
|
|
165
172
|
return;
|
|
166
173
|
}
|
|
167
|
-
if (!
|
|
174
|
+
if (!analysis.appearInValueParams) {
|
|
168
175
|
context.report({
|
|
169
176
|
node,
|
|
170
177
|
messageId: 'errorStringGeneric',
|
|
@@ -174,20 +181,4 @@ export const noHiddenTypeAssertions = createRule({
|
|
|
174
181
|
};
|
|
175
182
|
},
|
|
176
183
|
});
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const parameterTypeNodes = (parameters) => parameters.flatMap((parameter) => parameter.type !== undefined ? [parameter.type] : []);
|
|
182
|
-
const hasTypeNode = (typeElement) => {
|
|
183
|
-
try {
|
|
184
|
-
|
|
185
|
-
const typeAttr = typeElement
|
|
186
|
-
.type;
|
|
187
|
-
return typeAttr !== undefined && isTypeNode(typeAttr);
|
|
188
|
-
}
|
|
189
|
-
catch {
|
|
190
|
-
return false;
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
184
|
//# sourceMappingURL=no-hidden-type-assertions.mjs.map
|