eslint-config-typed 7.9.0 → 7.10.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.
Files changed (25) hide show
  1. package/dist/plugins/ts-restrictions/rules/no-optional-phantom-property.d.mts +44 -0
  2. package/dist/plugins/ts-restrictions/rules/no-optional-phantom-property.d.mts.map +1 -0
  3. package/dist/plugins/ts-restrictions/rules/no-optional-phantom-property.mjs +138 -0
  4. package/dist/plugins/ts-restrictions/rules/no-optional-phantom-property.mjs.map +1 -0
  5. package/dist/plugins/ts-restrictions/rules/rules.d.mts +1 -0
  6. package/dist/plugins/ts-restrictions/rules/rules.d.mts.map +1 -1
  7. package/dist/plugins/ts-restrictions/rules/rules.mjs +2 -0
  8. package/dist/plugins/ts-restrictions/rules/rules.mjs.map +1 -1
  9. package/dist/rules/eslint-import-rules.d.mts +1 -1
  10. package/dist/rules/eslint-import-rules.d.mts.map +1 -1
  11. package/dist/rules/eslint-import-rules.mjs +1 -0
  12. package/dist/rules/eslint-import-rules.mjs.map +1 -1
  13. package/dist/rules/eslint-ts-restrictions-rules.d.mts +1 -0
  14. package/dist/rules/eslint-ts-restrictions-rules.d.mts.map +1 -1
  15. package/dist/rules/eslint-ts-restrictions-rules.mjs +1 -0
  16. package/dist/rules/eslint-ts-restrictions-rules.mjs.map +1 -1
  17. package/dist/types/rules/eslint-ts-restrictions-rules.d.mts +14 -0
  18. package/dist/types/rules/eslint-ts-restrictions-rules.d.mts.map +1 -1
  19. package/package.json +2 -2
  20. package/src/plugins/ts-restrictions/rules/no-optional-phantom-property.mts +186 -0
  21. package/src/plugins/ts-restrictions/rules/no-optional-phantom-property.test.mts +365 -0
  22. package/src/plugins/ts-restrictions/rules/rules.mts +2 -0
  23. package/src/rules/eslint-import-rules.mts +1 -0
  24. package/src/rules/eslint-ts-restrictions-rules.mts +1 -0
  25. package/src/types/rules/eslint-ts-restrictions-rules.mts +15 -0
@@ -0,0 +1,44 @@
1
+ import { type TSESLint } from '@typescript-eslint/utils';
2
+ type Options = readonly [];
3
+ type MessageIds = 'optionalPhantom';
4
+ /**
5
+ * Disallow an optional property or method keyed by a type-only symbol: a
6
+ * `declare const tag: unique symbol` at the top level of a module that is not a
7
+ * declaration file.
8
+ *
9
+ * ## Why
10
+ *
11
+ * Such a symbol has no value at run time, so the property exists only in the
12
+ * type: a phantom marker. A marker like this usually stands for a claim, such
13
+ * as "this operator keeps the initial value" or "this value is validated".
14
+ * Optional, it is satisfied by every value that lacks it, so a function or an
15
+ * object that has not earned the claim is accepted with no `as`, and the type
16
+ * vouches for something the implementation never produced.
17
+ *
18
+ * Make the marker required, so that only an explicit `as` or a type guard can
19
+ * attach it, or move the claim into a type the implementation has to produce,
20
+ * such as the return type. See "Claims a value must earn" in
21
+ * `docs/typescript-coding-rules.md`.
22
+ *
23
+ * That is how a type-only symbol is written, and the only form reported. A
24
+ * symbol declared any other way is not reported: in a declaration file
25
+ * (`Symbol.iterator`, a library's `.d.mts`), in a script, in `declare global`,
26
+ * `declare module` or a namespace, or as a class member. A run-time global or a
27
+ * value a bundler's `define` injects is declared in `declare global`, not with
28
+ * a module-level `declare const`, which this rule takes for a phantom.
29
+ *
30
+ * An optional key whose type is `never`, `undefined` or `void`, or a union of
31
+ * them (`[tag]?: never`), says that a value must not carry the marker, which
32
+ * claims nothing, and is not reported.
33
+ *
34
+ * The rule reads the `?` written on a member. A phantom key made optional by a
35
+ * mapped type (`{ [P in typeof tag]?: K }`, `Partial<{ [tag]: K }>`) is not
36
+ * seen.
37
+ *
38
+ * The key is judged by its type, which is what names the property. A method
39
+ * with a body may wrap its key (`[tag as symbol]?() {}`), so the key is
40
+ * reported when its type at any wrapper layer is a type-only symbol.
41
+ */
42
+ export declare const noOptionalPhantomProperty: TSESLint.RuleModule<MessageIds, Options>;
43
+ export {};
44
+ //# sourceMappingURL=no-optional-phantom-property.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-optional-phantom-property.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/no-optional-phantom-property.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAKlC,KAAK,OAAO,GAAG,SAAS,EAAE,CAAC;AAE3B,KAAK,UAAU,GAAG,iBAAiB,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,UAAU,CACzD,UAAU,EACV,OAAO,CAyFC,CAAC"}
@@ -0,0 +1,138 @@
1
+ import { ESLintUtils, } from '@typescript-eslint/utils';
2
+ import { asNode, createGetLayerTypes } from 'eslint-rule-forge';
3
+ import * as ts from 'typescript';
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+ export const noOptionalPhantomProperty = {
43
+ meta: {
44
+ type: 'problem',
45
+ docs: {
46
+ description: 'Disallow an optional property keyed by a type-only symbol (`declare const tag: unique symbol`), which every value that lacks it satisfies',
47
+ },
48
+ schema: [],
49
+ messages: {
50
+ optionalPhantom: 'This optional property is keyed by a symbol that exists only in types, so every value that lacks it satisfies it and the claim it stands for is never checked. Make it required, so that only `as` or a type guard attaches it, or put the claim in a type the implementation must produce, such as its return type.',
51
+ },
52
+ defaultOptions: [],
53
+ },
54
+ create: (context) => {
55
+ const parserServices = ESLintUtils.getParserServices(context);
56
+ const typeOf = (node) => parserServices.getTypeAtLocation(asNode(node));
57
+ const getLayerTypes = createGetLayerTypes(parserServices);
58
+
59
+
60
+
61
+
62
+ const check = (node, annotation) => {
63
+ if (!node.optional || !node.computed) {
64
+ return;
65
+ }
66
+ if (!getLayerTypes(node.key).some(isTypeOnlySymbol)) {
67
+ return;
68
+ }
69
+ if (annotation !== undefined &&
70
+ claimsAbsence(typeOf(annotation.typeAnnotation))) {
71
+ return;
72
+ }
73
+ context.report({
74
+ node: asNode(node.key),
75
+ messageId: 'optionalPhantom',
76
+ });
77
+ };
78
+ return {
79
+ AccessorProperty: (node) => {
80
+ check(node, node.typeAnnotation);
81
+ },
82
+ MethodDefinition: (node) => {
83
+ check(node, undefined);
84
+ },
85
+ PropertyDefinition: (node) => {
86
+ check(node, node.typeAnnotation);
87
+ },
88
+ TSAbstractAccessorProperty: (node) => {
89
+ check(node, node.typeAnnotation);
90
+ },
91
+ TSAbstractMethodDefinition: (node) => {
92
+ check(node, undefined);
93
+ },
94
+ TSAbstractPropertyDefinition: (node) => {
95
+ check(node, node.typeAnnotation);
96
+ },
97
+ TSMethodSignature: (node) => {
98
+ check(node, undefined);
99
+ },
100
+ TSPropertySignature: (node) => {
101
+ check(node, node.typeAnnotation);
102
+ },
103
+ };
104
+ },
105
+ };
106
+
107
+
108
+
109
+
110
+
111
+ const isTypeOnlyDeclaration = (declaration) => {
112
+ if (!ts.isVariableDeclaration(declaration)) {
113
+ return false;
114
+ }
115
+
116
+ const statement = declaration.parent.parent;
117
+ return (ts.isVariableStatement(statement) &&
118
+ ts.isSourceFile(statement.parent) &&
119
+ !statement.parent.isDeclarationFile &&
120
+ ts.isExternalModule(statement.parent) &&
121
+ (ts.getModifiers(statement) ?? []).some((modifier) => modifier.kind === ts.SyntaxKind.DeclareKeyword));
122
+ };
123
+
124
+
125
+ const isTypeOnlySymbol = (type) => (type.flags & ts.TypeFlags.UniqueESSymbol) !== 0 &&
126
+ type.symbol.valueDeclaration !== undefined &&
127
+ isTypeOnlyDeclaration(type.symbol.valueDeclaration);
128
+
129
+
130
+
131
+
132
+
133
+ const claimsAbsence = (type) => type.isUnion()
134
+ ? type.types.every(claimsAbsence)
135
+ : (type.flags &
136
+ (ts.TypeFlags.Never | ts.TypeFlags.Undefined | ts.TypeFlags.Void)) !==
137
+ 0;
138
+ //# sourceMappingURL=no-optional-phantom-property.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-optional-phantom-property.mjs","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/no-optional-phantom-property.mts"],"names":[],"mappings":"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"}
@@ -15,6 +15,7 @@ export declare const tsRestrictionsRules: {
15
15
  readonly 'no-detached-jsdoc': import("@typescript-eslint/utils/ts-eslint").RuleModule<"detachedJsdoc", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
16
16
  readonly 'no-export-type-side-effects': import("@typescript-eslint/utils/ts-eslint").RuleModule<"importFromDeclaration" | "useTopLevelQualifier", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
17
17
  readonly 'no-negated-comparison': import("@typescript-eslint/utils/ts-eslint").RuleModule<"invertComparison" | "negatedComparison" | "negatedComparisonMaybeNaN", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
18
+ readonly 'no-optional-phantom-property': import("@typescript-eslint/utils/ts-eslint").RuleModule<"optionalPhantom", readonly [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
18
19
  readonly 'no-ragged-comment-wrap': import("@typescript-eslint/utils/ts-eslint").RuleModule<"raggedWrap", readonly [(Readonly<{
19
20
  printWidth?: number;
20
21
  }> | undefined)?], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
@@ -1 +1 @@
1
- {"version":3,"file":"rules.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/rules.mts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BU,CAAC"}
1
+ {"version":3,"file":"rules.d.mts","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/rules.mts"],"names":[],"mappings":"AA6BA,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BU,CAAC"}
@@ -7,6 +7,7 @@ import { noDateOnlyStringToDate } from './no-date-only-string-to-date.mjs';
7
7
  import { noDetachedJsdoc } from './no-detached-jsdoc.mjs';
8
8
  import { noExportTypeSideEffects } from './no-export-type-side-effects.mjs';
9
9
  import { noNegatedComparison } from './no-negated-comparison.mjs';
10
+ import { noOptionalPhantomProperty } from './no-optional-phantom-property.mjs';
10
11
  import { noRaggedCommentWrap } from './no-ragged-comment-wrap.mjs';
11
12
  import { noRestrictedCastName } from './no-restricted-cast-name.mjs';
12
13
  import { noRestrictedSyntax } from './no-restricted-syntax.mjs';
@@ -34,6 +35,7 @@ export const tsRestrictionsRules = {
34
35
  'no-detached-jsdoc': noDetachedJsdoc,
35
36
  'no-export-type-side-effects': noExportTypeSideEffects,
36
37
  'no-negated-comparison': noNegatedComparison,
38
+ 'no-optional-phantom-property': noOptionalPhantomProperty,
37
39
  'no-ragged-comment-wrap': noRaggedCommentWrap,
38
40
  'no-restricted-cast-name': noRestrictedCastName,
39
41
  'no-restricted-syntax': noRestrictedSyntax,
@@ -1 +1 @@
1
- {"version":3,"file":"rules.mjs","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/rules.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,8BAA8B,EAAE,MAAM,wCAAwC,CAAC;AACxF,OAAO,EAAE,+BAA+B,EAAE,MAAM,0CAA0C,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,8BAA8B,EAAE,MAAM,yCAAyC,CAAC;AACzF,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,+BAA+B,EAAE,MAAM,2CAA2C,CAAC;AAC5F,OAAO,EAAE,4BAA4B,EAAE,MAAM,wCAAwC,CAAC;AACtF,OAAO,EAAE,+BAA+B,EAAE,MAAM,2CAA2C,CAAC;AAC5F,OAAO,EAAE,8BAA8B,EAAE,MAAM,0CAA0C,CAAC;AAC1F,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAE1E,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,kCAAkC,EAAE,8BAA8B;IAClE,oCAAoC,EAAE,+BAA+B;IACrE,gBAAgB,EAAE,aAAa;IAC/B,8BAA8B,EAAE,yBAAyB;IACzD,8BAA8B,EAAE,uBAAuB;IACvD,6BAA6B,EAAE,sBAAsB;IACrD,mBAAmB,EAAE,eAAe;IACpC,6BAA6B,EAAE,uBAAuB;IACtD,uBAAuB,EAAE,mBAAmB;IAC5C,wBAAwB,EAAE,mBAAmB;IAC7C,yBAAyB,EAAE,oBAAoB;IAC/C,sBAAsB,EAAE,kBAAkB;IAC1C,kBAAkB,EAAE,cAAc;IAClC,2BAA2B,EAAE,sBAAsB;IACnD,mCAAmC,EAAE,8BAA8B;IACnE,cAAc,EAAE,WAAW;IAC3B,qBAAqB,EAAE,iBAAiB;IACxC,eAAe,EAAE,YAAY;IAC7B,oBAAoB,EAAE,gBAAgB;IACtC,qCAAqC,EAAE,+BAA+B;IACtE,kCAAkC,EAAE,4BAA4B;IAChE,qCAAqC,EAAE,+BAA+B;IACtE,oCAAoC,EAAE,8BAA8B;IACpE,mCAAmC,EAAE,4BAA4B;IACjE,gBAAgB,EAAE,aAAa;IAC/B,4BAA4B,EAAE,sBAAsB;CACZ,CAAC"}
1
+ {"version":3,"file":"rules.mjs","sourceRoot":"","sources":["../../../../src/plugins/ts-restrictions/rules/rules.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,8BAA8B,EAAE,MAAM,wCAAwC,CAAC;AACxF,OAAO,EAAE,+BAA+B,EAAE,MAAM,0CAA0C,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,8BAA8B,EAAE,MAAM,yCAAyC,CAAC;AACzF,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,+BAA+B,EAAE,MAAM,2CAA2C,CAAC;AAC5F,OAAO,EAAE,4BAA4B,EAAE,MAAM,wCAAwC,CAAC;AACtF,OAAO,EAAE,+BAA+B,EAAE,MAAM,2CAA2C,CAAC;AAC5F,OAAO,EAAE,8BAA8B,EAAE,MAAM,0CAA0C,CAAC;AAC1F,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAE1E,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,kCAAkC,EAAE,8BAA8B;IAClE,oCAAoC,EAAE,+BAA+B;IACrE,gBAAgB,EAAE,aAAa;IAC/B,8BAA8B,EAAE,yBAAyB;IACzD,8BAA8B,EAAE,uBAAuB;IACvD,6BAA6B,EAAE,sBAAsB;IACrD,mBAAmB,EAAE,eAAe;IACpC,6BAA6B,EAAE,uBAAuB;IACtD,uBAAuB,EAAE,mBAAmB;IAC5C,8BAA8B,EAAE,yBAAyB;IACzD,wBAAwB,EAAE,mBAAmB;IAC7C,yBAAyB,EAAE,oBAAoB;IAC/C,sBAAsB,EAAE,kBAAkB;IAC1C,kBAAkB,EAAE,cAAc;IAClC,2BAA2B,EAAE,sBAAsB;IACnD,mCAAmC,EAAE,8BAA8B;IACnE,cAAc,EAAE,WAAW;IAC3B,qBAAqB,EAAE,iBAAiB;IACxC,eAAe,EAAE,YAAY;IAC7B,oBAAoB,EAAE,gBAAgB;IACtC,qCAAqC,EAAE,+BAA+B;IACtE,kCAAkC,EAAE,4BAA4B;IAChE,qCAAqC,EAAE,+BAA+B;IACtE,oCAAoC,EAAE,8BAA8B;IACpE,mCAAmC,EAAE,4BAA4B;IACjE,gBAAgB,EAAE,aAAa;IAC/B,4BAA4B,EAAE,sBAAsB;CACZ,CAAC"}
@@ -7,7 +7,7 @@ export declare const eslintImportsRules: {
7
7
  readonly 'import-x/no-absolute-path': 1 | 2;
8
8
  readonly 'import-x/no-dynamic-require': 1 | 2;
9
9
  readonly 'import-x/no-internal-modules': readonly ["error", {
10
- readonly allow: readonly [`*/index.{${string}}`, `./index.{${string}}`, "rxjs/operators", "ts-data-forge/array", "ts-data-forge/number", "solid-js/web", "@testing-library/jest-dom/**", "react-dom/client", "preact/**", "immer/**", "firebase/*", "firebase-admin/*", "firebase-functions/**", "@blueprintjs/*", "@material-ui/**", "@mui/material", "@fontsource/**", "resize-observer/lib/ResizeObserverEntry", "vitest/config", "zx/globals"];
10
+ readonly allow: readonly [`*/index.{${string}}`, `./index.{${string}}`, "rxjs/operators", "ts-data-forge/array", "ts-data-forge/number", "solid-js/web", "@testing-library/jest-dom/**", "react-dom/client", "react-dom/server", "preact/**", "immer/**", "firebase/*", "firebase-admin/*", "firebase-functions/**", "@blueprintjs/*", "@material-ui/**", "@mui/material", "@fontsource/**", "resize-observer/lib/ResizeObserverEntry", "vitest/config", "zx/globals"];
11
11
  }];
12
12
  readonly 'import-x/no-webpack-loader-syntax': 'error';
13
13
  readonly 'import-x/no-self-import': 'error';
@@ -1 +1 @@
1
- {"version":3,"file":"eslint-import-rules.d.mts","sourceRoot":"","sources":["../../src/rules/eslint-import-rules.mts"],"names":[],"mappings":"AAGA,eAAO,MAAM,kBAAkB;uCAEH,KAAK;+BAOb,KAAK;iCACH,KAAK;mCACH,KAAK;6CACK,KAAK;;;;;;kDA8BA,OAAO;wCACjB,OAAO;;;oDAGK,KAAK;yDAOA,KAAK;;gCAO9B,KAAK;6CACQ,OAAO;oDAGA,KAAK;uCAGlB,KAAK;oDAEQ,KAAK;4CACb,OAAO;2CAIR,KAAK;qCAGX,OAAO;qCACP,KAAK;gCACV,OAAO;2CACI,KAAK;kDACE,KAAK;;sCAIjB,KAAK;;;;sCAEL,KAAK;;;qBAKf,IAAI,EAAE,QAAQ;qBAAE,GAAG,EAAE,QAAQ;;;+BAI1B,KAAK;;;wBAYZ,CAAC;;0CAIiB,KAAK;;;;0CAYL,KAAK;IAElC;;;OAGG;2CAC2B,OAAO;+CACH,KAAK;yCAEX,KAAK;;uCAEP,KAAK;kDAEM,KAAK;+CAER,OAAO;;iDAQL,KAAK;uCAIf,CAAC;CACU,CAAC"}
1
+ {"version":3,"file":"eslint-import-rules.d.mts","sourceRoot":"","sources":["../../src/rules/eslint-import-rules.mts"],"names":[],"mappings":"AAGA,eAAO,MAAM,kBAAkB;uCAEH,KAAK;+BAOb,KAAK;iCACH,KAAK;mCACH,KAAK;6CACK,KAAK;;;;;;kDA+BA,OAAO;wCACjB,OAAO;;;oDAGK,KAAK;yDAOA,KAAK;;gCAO9B,KAAK;6CACQ,OAAO;oDAGA,KAAK;uCAGlB,KAAK;oDAEQ,KAAK;4CACb,OAAO;2CAIR,KAAK;qCAGX,OAAO;qCACP,KAAK;gCACV,OAAO;2CACI,KAAK;kDACE,KAAK;;sCAIjB,KAAK;;;;sCAEL,KAAK;;;qBAKf,IAAI,EAAE,QAAQ;qBAAE,GAAG,EAAE,QAAQ;;;+BAI1B,KAAK;;;wBAYZ,CAAC;;0CAIiB,KAAK;;;;0CAYL,KAAK;IAElC;;;OAGG;2CAC2B,OAAO;+CACH,KAAK;yCAEX,KAAK;;uCAEP,KAAK;kDAEM,KAAK;+CAER,OAAO;;iDAQL,KAAK;uCAIf,CAAC;CACU,CAAC"}
@@ -26,6 +26,7 @@ export const eslintImportsRules = {
26
26
  'solid-js/web',
27
27
  '@testing-library/jest-dom/**',
28
28
  'react-dom/client',
29
+ 'react-dom/server',
29
30
  'preact/**',
30
31
  'immer/**',
31
32
  'firebase/*',
@@ -1 +1 @@
1
- {"version":3,"file":"eslint-import-rules.mjs","sourceRoot":"","sources":["../../src/rules/eslint-import-rules.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"eslint-import-rules.mjs","sourceRoot":"","sources":["../../src/rules/eslint-import-rules.mts"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@ export declare const eslintTsRestrictionsRules: {
8
8
  readonly 'ts-restrictions/no-date-only-string-to-date': 1 | 2;
9
9
  readonly 'ts-restrictions/no-negated-comparison': 'error';
10
10
  readonly 'ts-restrictions/no-detached-jsdoc': 'error';
11
+ readonly 'ts-restrictions/no-optional-phantom-property': 'error';
11
12
  readonly 'ts-restrictions/no-export-type-side-effects': 'error';
12
13
  readonly 'ts-restrictions/no-ragged-comment-wrap': 1 | 2;
13
14
  readonly 'ts-restrictions/no-string-spread': 'error';
@@ -1 +1 @@
1
- {"version":3,"file":"eslint-ts-restrictions-rules.d.mts","sourceRoot":"","sources":["../../src/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"AAKA,eAAO,MAAM,yBAAyB;qDACI,KAAK;wDACF,KAAK;mEACM,OAAO;+CAC3B,OAAO;6DACO,OAAO;;;sDAGd,OAAO;kDACX,OAAO;4DACG,OAAO;;iDAElB,OAAO;0DACE,OAAO;kEACC,OAAO;6CAC5B,OAAO;oDACA,OAAO;8CACb,OAAO;mDACF,OAAO;iEACO,OAAO;oEACJ,OAAO;oEACP,OAAO;mEACR,OAAO;kEACR,OAAO;;;;CAKhB,CAAC"}
1
+ {"version":3,"file":"eslint-ts-restrictions-rules.d.mts","sourceRoot":"","sources":["../../src/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"AAKA,eAAO,MAAM,yBAAyB;qDACI,KAAK;wDACF,KAAK;mEACM,OAAO;+CAC3B,OAAO;6DACO,OAAO;;;sDAGd,OAAO;kDACX,OAAO;6DACI,OAAO;4DACR,OAAO;;iDAElB,OAAO;0DACE,OAAO;kEACC,OAAO;6CAC5B,OAAO;oDACA,OAAO;8CACb,OAAO;mDACF,OAAO;iEACO,OAAO;oEACJ,OAAO;oEACP,OAAO;mEACR,OAAO;kEACR,OAAO;;;;CAKhB,CAAC"}
@@ -9,6 +9,7 @@ export const eslintTsRestrictionsRules = {
9
9
  'ts-restrictions/no-date-only-string-to-date': withDefaultOption('error'),
10
10
  'ts-restrictions/no-negated-comparison': 'error',
11
11
  'ts-restrictions/no-detached-jsdoc': 'error',
12
+ 'ts-restrictions/no-optional-phantom-property': 'error',
12
13
  'ts-restrictions/no-export-type-side-effects': 'error',
13
14
  'ts-restrictions/no-ragged-comment-wrap': withDefaultOption('error'),
14
15
  'ts-restrictions/no-string-spread': 'error',
@@ -1 +1 @@
1
- {"version":3,"file":"eslint-ts-restrictions-rules.mjs","sourceRoot":"","sources":["../../src/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,sCAAsC,EAAE,KAAK;IAC7C,yCAAyC,EAAE,KAAK;IAChD,oDAAoD,EAAE,OAAO;IAC7D,gCAAgC,EAAE,OAAO;IACzC,8CAA8C,EAAE,OAAO;IACvD,8CAA8C,EAAE,iBAAiB,CAAC,OAAO,CAAC;IAC1E,6CAA6C,EAAE,iBAAiB,CAAC,OAAO,CAAC;IACzE,uCAAuC,EAAE,OAAO;IAChD,mCAAmC,EAAE,OAAO;IAC5C,6CAA6C,EAAE,OAAO;IACtD,wCAAwC,EAAE,iBAAiB,CAAC,OAAO,CAAC;IACpE,kCAAkC,EAAE,OAAO;IAC3C,2CAA2C,EAAE,OAAO;IACpD,mDAAmD,EAAE,OAAO;IAC5D,8BAA8B,EAAE,OAAO;IACvC,qCAAqC,EAAE,OAAO;IAC9C,+BAA+B,EAAE,OAAO;IACxC,oCAAoC,EAAE,OAAO;IAC7C,kDAAkD,EAAE,OAAO;IAC3D,qDAAqD,EAAE,OAAO;IAC9D,qDAAqD,EAAE,OAAO;IAC9D,oDAAoD,EAAE,OAAO;IAC7D,mDAAmD,EAAE,OAAO;IAC5D,gCAAgC,EAAE,CAAC,OAAO,EAAE,kBAAkB,CAAC;IAC/D,4CAA4C,EAAE,iBAAiB,CAAC,OAAO,CAAC;IACxE,kDAAkD,EAChD,iBAAiB,CAAC,OAAO,CAAC;CACgB,CAAC"}
1
+ {"version":3,"file":"eslint-ts-restrictions-rules.mjs","sourceRoot":"","sources":["../../src/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,sCAAsC,EAAE,KAAK;IAC7C,yCAAyC,EAAE,KAAK;IAChD,oDAAoD,EAAE,OAAO;IAC7D,gCAAgC,EAAE,OAAO;IACzC,8CAA8C,EAAE,OAAO;IACvD,8CAA8C,EAAE,iBAAiB,CAAC,OAAO,CAAC;IAC1E,6CAA6C,EAAE,iBAAiB,CAAC,OAAO,CAAC;IACzE,uCAAuC,EAAE,OAAO;IAChD,mCAAmC,EAAE,OAAO;IAC5C,8CAA8C,EAAE,OAAO;IACvD,6CAA6C,EAAE,OAAO;IACtD,wCAAwC,EAAE,iBAAiB,CAAC,OAAO,CAAC;IACpE,kCAAkC,EAAE,OAAO;IAC3C,2CAA2C,EAAE,OAAO;IACpD,mDAAmD,EAAE,OAAO;IAC5D,8BAA8B,EAAE,OAAO;IACvC,qCAAqC,EAAE,OAAO;IAC9C,+BAA+B,EAAE,OAAO;IACxC,oCAAoC,EAAE,OAAO;IAC7C,kDAAkD,EAAE,OAAO;IAC3D,qDAAqD,EAAE,OAAO;IAC9D,qDAAqD,EAAE,OAAO;IAC9D,oDAAoD,EAAE,OAAO;IAC7D,mDAAmD,EAAE,OAAO;IAC5D,gCAAgC,EAAE,CAAC,OAAO,EAAE,kBAAkB,CAAC;IAC/D,4CAA4C,EAAE,iBAAiB,CAAC,OAAO,CAAC;IACxE,kDAAkD,EAChD,iBAAiB,CAAC,OAAO,CAAC;CACgB,CAAC"}
@@ -210,6 +210,19 @@ declare namespace NoExportTypeSideEffects {
210
210
  declare namespace NoNegatedComparison {
211
211
  type RuleEntry = Linter.StringSeverity;
212
212
  }
213
+ /**
214
+ * @description Disallow an optional property keyed by a type-only symbol (`declare const tag: unique symbol`), which every value that lacks it satisfies
215
+ *
216
+ * ```md
217
+ * | key | value |
218
+ * | :--------- | :------ |
219
+ * | type | problem |
220
+ * | deprecated | false |
221
+ * ```
222
+ */
223
+ declare namespace NoOptionalPhantomProperty {
224
+ type RuleEntry = Linter.StringSeverity;
225
+ }
213
226
  /**
214
227
  * @description Disallow a comment paragraph wrapped unevenly: a line with room for the first word of the line after it
215
228
  *
@@ -659,6 +672,7 @@ export type EslintTsRestrictionsRules = Readonly<{
659
672
  'ts-restrictions/no-detached-jsdoc': NoDetachedJsdoc.RuleEntry;
660
673
  'ts-restrictions/no-export-type-side-effects': NoExportTypeSideEffects.RuleEntry;
661
674
  'ts-restrictions/no-negated-comparison': NoNegatedComparison.RuleEntry;
675
+ 'ts-restrictions/no-optional-phantom-property': NoOptionalPhantomProperty.RuleEntry;
662
676
  'ts-restrictions/no-ragged-comment-wrap': NoRaggedCommentWrap.RuleEntry;
663
677
  'ts-restrictions/no-restricted-cast-name': NoRestrictedCastName.RuleEntry;
664
678
  'ts-restrictions/no-restricted-syntax': NoRestrictedSyntax.RuleEntry;
@@ -1 +1 @@
1
- {"version":3,"file":"eslint-ts-restrictions-rules.d.mts","sourceRoot":"","sources":["../../../src/types/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"eslint-ts-restrictions-rules.d.mts","sourceRoot":"","sources":["../../../src/types/rules/eslint-ts-restrictions-rules.mts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-config-typed",
3
- "version": "7.9.0",
3
+ "version": "7.10.0",
4
4
  "private": false,
5
5
  "keywords": [
6
6
  "typescript"
@@ -91,7 +91,7 @@
91
91
  "@vitest/ui": "5.0.5",
92
92
  "cspell": "10.4.0",
93
93
  "dedent": "1.7.2",
94
- "eslint-config-typed": "7.9.0",
94
+ "eslint-config-typed": "7.10.0",
95
95
  "eslint-plugin-ts-data-forge": "0.11.2",
96
96
  "eslint-plugin-ts-fortress": "1.3.17",
97
97
  "eslint-plugin-ts-type-forge": "0.8.24",
@@ -0,0 +1,186 @@
1
+ import {
2
+ ESLintUtils,
3
+ type TSESLint,
4
+ type TSESTree,
5
+ } from '@typescript-eslint/utils';
6
+ import { asNode, createGetLayerTypes } from 'eslint-rule-forge';
7
+ import type { DeepReadonly } from 'ts-type-forge';
8
+ import * as ts from 'typescript';
9
+
10
+ type Options = readonly [];
11
+
12
+ type MessageIds = 'optionalPhantom';
13
+
14
+ /**
15
+ * Disallow an optional property or method keyed by a type-only symbol: a
16
+ * `declare const tag: unique symbol` at the top level of a module that is not a
17
+ * declaration file.
18
+ *
19
+ * ## Why
20
+ *
21
+ * Such a symbol has no value at run time, so the property exists only in the
22
+ * type: a phantom marker. A marker like this usually stands for a claim, such
23
+ * as "this operator keeps the initial value" or "this value is validated".
24
+ * Optional, it is satisfied by every value that lacks it, so a function or an
25
+ * object that has not earned the claim is accepted with no `as`, and the type
26
+ * vouches for something the implementation never produced.
27
+ *
28
+ * Make the marker required, so that only an explicit `as` or a type guard can
29
+ * attach it, or move the claim into a type the implementation has to produce,
30
+ * such as the return type. See "Claims a value must earn" in
31
+ * `docs/typescript-coding-rules.md`.
32
+ *
33
+ * That is how a type-only symbol is written, and the only form reported. A
34
+ * symbol declared any other way is not reported: in a declaration file
35
+ * (`Symbol.iterator`, a library's `.d.mts`), in a script, in `declare global`,
36
+ * `declare module` or a namespace, or as a class member. A run-time global or a
37
+ * value a bundler's `define` injects is declared in `declare global`, not with
38
+ * a module-level `declare const`, which this rule takes for a phantom.
39
+ *
40
+ * An optional key whose type is `never`, `undefined` or `void`, or a union of
41
+ * them (`[tag]?: never`), says that a value must not carry the marker, which
42
+ * claims nothing, and is not reported.
43
+ *
44
+ * The rule reads the `?` written on a member. A phantom key made optional by a
45
+ * mapped type (`{ [P in typeof tag]?: K }`, `Partial<{ [tag]: K }>`) is not
46
+ * seen.
47
+ *
48
+ * The key is judged by its type, which is what names the property. A method
49
+ * with a body may wrap its key (`[tag as symbol]?() {}`), so the key is
50
+ * reported when its type at any wrapper layer is a type-only symbol.
51
+ */
52
+ export const noOptionalPhantomProperty: TSESLint.RuleModule<
53
+ MessageIds,
54
+ Options
55
+ > = {
56
+ meta: {
57
+ type: 'problem',
58
+ docs: {
59
+ description:
60
+ 'Disallow an optional property keyed by a type-only symbol (`declare const tag: unique symbol`), which every value that lacks it satisfies',
61
+ },
62
+ schema: [],
63
+ messages: {
64
+ optionalPhantom:
65
+ 'This optional property is keyed by a symbol that exists only in types, so every value that lacks it satisfies it and the claim it stands for is never checked. Make it required, so that only `as` or a type guard attaches it, or put the claim in a type the implementation must produce, such as its return type.',
66
+ },
67
+ defaultOptions: [],
68
+ },
69
+
70
+ create: (context) => {
71
+ const parserServices = ESLintUtils.getParserServices(context);
72
+
73
+ const typeOf = (node: DeepReadonly<TSESTree.Node>): ts.Type =>
74
+ parserServices.getTypeAtLocation(asNode(node));
75
+
76
+ const getLayerTypes = createGetLayerTypes(parserServices);
77
+
78
+ /**
79
+ * Reports `node` when it is optional, keyed by a type-only symbol, and its
80
+ * `annotation` (a method has none) does not say the marker must be absent.
81
+ */
82
+ const check = (
83
+ node: DeepReadonly<
84
+ | TSESTree.AccessorProperty
85
+ | TSESTree.MethodDefinition
86
+ | TSESTree.PropertyDefinition
87
+ | TSESTree.TSAbstractAccessorProperty
88
+ | TSESTree.TSAbstractMethodDefinition
89
+ | TSESTree.TSAbstractPropertyDefinition
90
+ | TSESTree.TSMethodSignature
91
+ | TSESTree.TSPropertySignature
92
+ >,
93
+ annotation: DeepReadonly<TSESTree.TSTypeAnnotation> | undefined,
94
+ ): void => {
95
+ if (!node.optional || !node.computed) {
96
+ return;
97
+ }
98
+
99
+ if (!getLayerTypes(node.key).some(isTypeOnlySymbol)) {
100
+ return;
101
+ }
102
+
103
+ if (
104
+ annotation !== undefined &&
105
+ claimsAbsence(typeOf(annotation.typeAnnotation))
106
+ ) {
107
+ return;
108
+ }
109
+
110
+ context.report({
111
+ node: asNode(node.key),
112
+ messageId: 'optionalPhantom',
113
+ });
114
+ };
115
+
116
+ return {
117
+ AccessorProperty: (node) => {
118
+ check(node, node.typeAnnotation);
119
+ },
120
+ MethodDefinition: (node) => {
121
+ check(node, undefined);
122
+ },
123
+ PropertyDefinition: (node) => {
124
+ check(node, node.typeAnnotation);
125
+ },
126
+ TSAbstractAccessorProperty: (node) => {
127
+ check(node, node.typeAnnotation);
128
+ },
129
+ TSAbstractMethodDefinition: (node) => {
130
+ check(node, undefined);
131
+ },
132
+ TSAbstractPropertyDefinition: (node) => {
133
+ check(node, node.typeAnnotation);
134
+ },
135
+ TSMethodSignature: (node) => {
136
+ check(node, undefined);
137
+ },
138
+ TSPropertySignature: (node) => {
139
+ check(node, node.typeAnnotation);
140
+ },
141
+ };
142
+ },
143
+ } as const;
144
+
145
+ /**
146
+ * Whether `declaration` is a `declare const` at the top level of a module that
147
+ * is not a declaration file, so that it has no value at run time.
148
+ */
149
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types -- a compiler node, read only
150
+ const isTypeOnlyDeclaration = (declaration: ts.Declaration): boolean => {
151
+ if (!ts.isVariableDeclaration(declaration)) {
152
+ return false;
153
+ }
154
+
155
+ // A `for` loop's declaration list has no statement of its own.
156
+ const statement = declaration.parent.parent;
157
+
158
+ return (
159
+ ts.isVariableStatement(statement) &&
160
+ ts.isSourceFile(statement.parent) &&
161
+ !statement.parent.isDeclarationFile &&
162
+ ts.isExternalModule(statement.parent) &&
163
+ (ts.getModifiers(statement) ?? []).some(
164
+ (modifier) => modifier.kind === ts.SyntaxKind.DeclareKeyword,
165
+ )
166
+ );
167
+ };
168
+
169
+ /** Whether `type` is a `unique symbol` that has no value at run time. */
170
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types -- a compiler type, read only
171
+ const isTypeOnlySymbol = (type: ts.Type): boolean =>
172
+ (type.flags & ts.TypeFlags.UniqueESSymbol) !== 0 &&
173
+ type.symbol.valueDeclaration !== undefined &&
174
+ isTypeOnlyDeclaration(type.symbol.valueDeclaration);
175
+
176
+ /**
177
+ * Whether a property's type says that a value must not have it: `never`,
178
+ * `undefined`, `void`, or a union of them.
179
+ */
180
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types -- a compiler type, read only
181
+ const claimsAbsence = (type: ts.Type): boolean =>
182
+ type.isUnion()
183
+ ? type.types.every(claimsAbsence)
184
+ : (type.flags &
185
+ (ts.TypeFlags.Never | ts.TypeFlags.Undefined | ts.TypeFlags.Void)) !==
186
+ 0;
@@ -0,0 +1,365 @@
1
+ import parser from '@typescript-eslint/parser';
2
+ import { RuleTester } from '@typescript-eslint/rule-tester';
3
+ import dedent from 'dedent';
4
+ import { noOptionalPhantomProperty } from './no-optional-phantom-property.mjs';
5
+
6
+ const tester = new RuleTester({
7
+ languageOptions: {
8
+ parser,
9
+ parserOptions: {
10
+ ecmaVersion: 2022,
11
+ sourceType: 'module',
12
+ projectService: {
13
+ allowDefaultProject: ['*.ts*'],
14
+ },
15
+ tsconfigRootDir: `${import.meta.dirname}/../../../..`,
16
+ },
17
+ },
18
+ });
19
+
20
+ describe('no-optional-phantom-property', () => {
21
+ tester.run('no-optional-phantom-property', noOptionalPhantomProperty, {
22
+ valid: [
23
+ {
24
+ name: 'a required property keyed by a type-only symbol',
25
+ code: dedent`
26
+ declare const initializedTag: unique symbol;
27
+ export type Initialized = Readonly<{ [initializedTag]: true }>;
28
+ `,
29
+ },
30
+ {
31
+ name: 'an optional property keyed by a symbol that exists at run time',
32
+ code: dedent`
33
+ const brand: unique symbol = Symbol('brand');
34
+ export type Branded = Readonly<{ [brand]?: true }>;
35
+ `,
36
+ },
37
+ {
38
+ name: 'an optional property keyed by a well-known symbol from a declaration file',
39
+ code: dedent`
40
+ export type MaybeIterable = Readonly<{
41
+ [Symbol.iterator]?: () => Iterator<number>;
42
+ }>;
43
+ `,
44
+ },
45
+ {
46
+ name: 'an optional property keyed by a symbol from a declaration file',
47
+ code: dedent`
48
+ import { declaredSymbol } from './test/declared-symbol.mjs';
49
+
50
+ export type Declared = Readonly<{ [declaredSymbol]?: unknown }>;
51
+ `,
52
+ },
53
+ {
54
+ name: 'an optional key typed never, which says the marker must be absent',
55
+ code: dedent`
56
+ declare const validated: unique symbol;
57
+ export type NotValidated = Readonly<{ [validated]?: never }>;
58
+ `,
59
+ },
60
+ {
61
+ name: 'a symbol in declare module, which may exist at run time',
62
+ code: dedent`
63
+ import { libraryTag } from 'dedent';
64
+
65
+ declare module 'dedent' {
66
+ const libraryTag: unique symbol;
67
+ }
68
+
69
+ export type Tagged = Readonly<{ [libraryTag]?: true }>;
70
+ `,
71
+ },
72
+ {
73
+ name: 'an optional key typed void',
74
+ code: dedent`
75
+ declare const validated: unique symbol;
76
+ export type NotValidated = Readonly<{ [validated]?: void }>;
77
+ `,
78
+ },
79
+ {
80
+ name: 'an optional key typed a union of absent types',
81
+ code: dedent`
82
+ declare const validated: unique symbol;
83
+ export type NotValidated = Readonly<{ [validated]?: undefined | void }>;
84
+ `,
85
+ },
86
+ {
87
+ name: 'an optional key typed undefined',
88
+ code: dedent`
89
+ declare const validated: unique symbol;
90
+ export interface NotValidated {
91
+ readonly [validated]?: undefined;
92
+ }
93
+ `,
94
+ },
95
+ {
96
+ name: 'an optional property with a plain name',
97
+ code: dedent`
98
+ export type Options = Readonly<{ kind?: 'keep' }>;
99
+ `,
100
+ },
101
+ {
102
+ name: 'an optional property keyed by a string literal',
103
+ code: dedent`
104
+ export type Options = Readonly<{ ['kind']?: 'keep' }>;
105
+ `,
106
+ },
107
+ {
108
+ name: 'an optional property keyed by a declared string, which names a real property',
109
+ code: dedent`
110
+ declare const key: 'kind';
111
+ export type Options = Readonly<{ [key]?: 'keep' }>;
112
+ `,
113
+ },
114
+ {
115
+ name: 'a symbol in declare global, which may exist at run time',
116
+ code: dedent`
117
+ declare global {
118
+ const polyfillTag: unique symbol;
119
+ }
120
+ export type Tagged = Readonly<{ [polyfillTag]?: true }>;
121
+ `,
122
+ },
123
+ {
124
+ name: 'a symbol in a declared namespace, which may be merged with a run-time value',
125
+ code: dedent`
126
+ export function Tags(): void {}
127
+ export declare namespace Tags {
128
+ const kind: unique symbol;
129
+ }
130
+ export type Tagged = Readonly<{ [Tags.kind]?: 'keep' }>;
131
+ `,
132
+ },
133
+ {
134
+ name: 'a declare static member, which a static block may supply',
135
+ code: dedent`
136
+ export class Tags {
137
+ declare static readonly kind: unique symbol;
138
+ }
139
+ export type Tagged = Readonly<{ [Tags.kind]?: 'keep' }>;
140
+ `,
141
+ },
142
+ {
143
+ name: 'a required class property keyed by a type-only symbol',
144
+ code: dedent`
145
+ declare const tag: unique symbol;
146
+ export class Tagged {
147
+ declare readonly [tag]: true;
148
+ }
149
+ `,
150
+ },
151
+ ],
152
+ invalid: [
153
+ {
154
+ name: 'an optional property in a type literal',
155
+ code: dedent`
156
+ declare const initKindTag: unique symbol;
157
+ export type Operator<K> = ((x: number) => number) &
158
+ Readonly<{ [initKindTag]?: K }>;
159
+ `,
160
+ errors: [{ messageId: 'optionalPhantom' }],
161
+ },
162
+ {
163
+ name: 'an optional property in an interface',
164
+ code: dedent`
165
+ declare const tag: unique symbol;
166
+ export interface Tagged {
167
+ readonly [tag]?: true;
168
+ }
169
+ `,
170
+ errors: [{ messageId: 'optionalPhantom' }],
171
+ },
172
+ {
173
+ name: 'an optional method signature',
174
+ code: dedent`
175
+ declare const tag: unique symbol;
176
+ export interface Tagged {
177
+ [tag]?(): void;
178
+ }
179
+ `,
180
+ errors: [{ messageId: 'optionalPhantom' }],
181
+ },
182
+ {
183
+ name: 'an exported type-only symbol',
184
+ code: dedent`
185
+ export declare const tag: unique symbol;
186
+ export type Tagged = Readonly<{ [tag]?: true }>;
187
+ `,
188
+ errors: [{ messageId: 'optionalPhantom' }],
189
+ },
190
+ {
191
+ name: 'a type-only symbol reached through an import alias',
192
+ code: dedent`
193
+ import { tag as aliased } from './file.js';
194
+
195
+ export declare const tag: unique symbol;
196
+ export type Tagged = Readonly<{ [aliased]?: true }>;
197
+ `,
198
+ errors: [{ messageId: 'optionalPhantom' }],
199
+ },
200
+ {
201
+ name: 'a type-only symbol that a type alias of the same name merges with',
202
+ code: dedent`
203
+ declare const tag: unique symbol;
204
+ type tag = typeof tag;
205
+ export type Tagged = Readonly<{ [tag]?: tag }>;
206
+ `,
207
+ errors: [{ messageId: 'optionalPhantom' }],
208
+ },
209
+ {
210
+ name: 'an optional class property',
211
+ code: dedent`
212
+ declare const tag: unique symbol;
213
+ export class Tagged {
214
+ declare readonly [tag]?: true;
215
+ }
216
+ `,
217
+ errors: [{ messageId: 'optionalPhantom' }],
218
+ },
219
+ {
220
+ name: 'an optional abstract class property',
221
+ code: dedent`
222
+ declare const tag: unique symbol;
223
+ export abstract class Tagged {
224
+ abstract readonly [tag]?: true;
225
+ }
226
+ `,
227
+ errors: [{ messageId: 'optionalPhantom' }],
228
+ },
229
+ {
230
+ name: 'an optional class method',
231
+ code: dedent`
232
+ declare const tag: unique symbol;
233
+ export abstract class Tagged {
234
+ abstract [tag]?(): void;
235
+ }
236
+ `,
237
+ errors: [{ messageId: 'optionalPhantom' }],
238
+ },
239
+ {
240
+ name: 'an optional abstract accessor',
241
+ code: dedent`
242
+ declare const tag: unique symbol;
243
+ export abstract class Tagged {
244
+ abstract accessor [tag]?: true;
245
+ }
246
+ `,
247
+ errors: [{ messageId: 'optionalPhantom' }],
248
+ },
249
+ {
250
+ name: 'an optional key typed never alongside other types',
251
+ code: dedent`
252
+ declare const tag: unique symbol;
253
+ export type Tagged = Readonly<{ [tag]?: true | never }>;
254
+ `,
255
+ errors: [{ messageId: 'optionalPhantom' }],
256
+ },
257
+ {
258
+ name: 'an optional method and accessor of a declared class',
259
+ code: dedent`
260
+ declare const a: unique symbol;
261
+ declare const b: unique symbol;
262
+ export declare class Tagged {
263
+ [a]?(): void;
264
+ accessor [b]?: true;
265
+ }
266
+ `,
267
+ errors: [
268
+ { messageId: 'optionalPhantom' },
269
+ { messageId: 'optionalPhantom' },
270
+ ],
271
+ },
272
+ {
273
+ name: 'one report per optional property',
274
+ code: dedent`
275
+ declare const a: unique symbol;
276
+ declare const b: unique symbol;
277
+ export type Tagged = Readonly<{ [a]?: 1; [b]?: 2 }>;
278
+ `,
279
+ errors: [
280
+ { messageId: 'optionalPhantom' },
281
+ { messageId: 'optionalPhantom' },
282
+ ],
283
+ },
284
+ ],
285
+ });
286
+
287
+ describe('through type wrappers', () => {
288
+ tester.run('no-optional-phantom-property', noOptionalPhantomProperty, {
289
+ valid: [
290
+ {
291
+ name: 'a runtime symbol widened by as on a method key',
292
+ code: dedent`
293
+ const brand: unique symbol = Symbol('brand');
294
+ export abstract class Branded {
295
+ [brand as symbol]?(): void {}
296
+ }
297
+ `,
298
+ },
299
+ ],
300
+ invalid: [
301
+ {
302
+ name: 'a type-only symbol widened by as on a method key',
303
+ code: dedent`
304
+ declare const tag: unique symbol;
305
+ export abstract class Tagged {
306
+ [tag as symbol]?(): void {}
307
+ }
308
+ `,
309
+ errors: [{ messageId: 'optionalPhantom' }],
310
+ },
311
+ {
312
+ name: 'a type-only symbol behind satisfies on a method key',
313
+ code: dedent`
314
+ declare const tag: unique symbol;
315
+ export abstract class Tagged {
316
+ [tag satisfies symbol]?(): void {}
317
+ }
318
+ `,
319
+ errors: [{ messageId: 'optionalPhantom' }],
320
+ },
321
+ {
322
+ name: 'a type-only symbol behind a non-null assertion on a method key',
323
+ code: dedent`
324
+ declare const tag: unique symbol;
325
+ export abstract class Tagged {
326
+ [tag!]?(): void {}
327
+ }
328
+ `,
329
+ errors: [{ messageId: 'optionalPhantom' }],
330
+ },
331
+ {
332
+ name: 'a type-only symbol behind an angle-bracket assertion on a method key',
333
+ code: dedent`
334
+ declare const tag: unique symbol;
335
+ export abstract class Tagged {
336
+ [<symbol>tag]?(): void {}
337
+ }
338
+ `,
339
+ errors: [{ messageId: 'optionalPhantom' }],
340
+ },
341
+ {
342
+ name: 'a type-only symbol in parentheses on a method key',
343
+ code: dedent`
344
+ declare const tag: unique symbol;
345
+ export abstract class Tagged {
346
+ [(tag)]?(): void {}
347
+ }
348
+ `,
349
+ errors: [{ messageId: 'optionalPhantom' }],
350
+ },
351
+ {
352
+ name: 'a runtime symbol cast to a type-only one on a method key',
353
+ code: dedent`
354
+ declare const tag: unique symbol;
355
+ const brand: unique symbol = Symbol('brand');
356
+ export abstract class Tagged {
357
+ [brand as unknown as typeof tag]?(): void {}
358
+ }
359
+ `,
360
+ errors: [{ messageId: 'optionalPhantom' }],
361
+ },
362
+ ],
363
+ });
364
+ });
365
+ });
@@ -8,6 +8,7 @@ import { noDateOnlyStringToDate } from './no-date-only-string-to-date.mjs';
8
8
  import { noDetachedJsdoc } from './no-detached-jsdoc.mjs';
9
9
  import { noExportTypeSideEffects } from './no-export-type-side-effects.mjs';
10
10
  import { noNegatedComparison } from './no-negated-comparison.mjs';
11
+ import { noOptionalPhantomProperty } from './no-optional-phantom-property.mjs';
11
12
  import { noRaggedCommentWrap } from './no-ragged-comment-wrap.mjs';
12
13
  import { noRestrictedCastName } from './no-restricted-cast-name.mjs';
13
14
  import { noRestrictedSyntax } from './no-restricted-syntax.mjs';
@@ -36,6 +37,7 @@ export const tsRestrictionsRules = {
36
37
  'no-detached-jsdoc': noDetachedJsdoc,
37
38
  'no-export-type-side-effects': noExportTypeSideEffects,
38
39
  'no-negated-comparison': noNegatedComparison,
40
+ 'no-optional-phantom-property': noOptionalPhantomProperty,
39
41
  'no-ragged-comment-wrap': noRaggedCommentWrap,
40
42
  'no-restricted-cast-name': noRestrictedCastName,
41
43
  'no-restricted-syntax': noRestrictedSyntax,
@@ -28,6 +28,7 @@ export const eslintImportsRules = {
28
28
  'solid-js/web',
29
29
  '@testing-library/jest-dom/**',
30
30
  'react-dom/client',
31
+ 'react-dom/server',
31
32
  'preact/**',
32
33
  'immer/**',
33
34
  'firebase/*',
@@ -13,6 +13,7 @@ export const eslintTsRestrictionsRules = {
13
13
  'ts-restrictions/no-date-only-string-to-date': withDefaultOption('error'),
14
14
  'ts-restrictions/no-negated-comparison': 'error',
15
15
  'ts-restrictions/no-detached-jsdoc': 'error',
16
+ 'ts-restrictions/no-optional-phantom-property': 'error',
16
17
  'ts-restrictions/no-export-type-side-effects': 'error',
17
18
  'ts-restrictions/no-ragged-comment-wrap': withDefaultOption('error'),
18
19
  'ts-restrictions/no-string-spread': 'error',
@@ -232,6 +232,20 @@ namespace NoNegatedComparison {
232
232
  export type RuleEntry = Linter.StringSeverity;
233
233
  }
234
234
 
235
+ /**
236
+ * @description Disallow an optional property keyed by a type-only symbol (`declare const tag: unique symbol`), which every value that lacks it satisfies
237
+ *
238
+ * ```md
239
+ * | key | value |
240
+ * | :--------- | :------ |
241
+ * | type | problem |
242
+ * | deprecated | false |
243
+ * ```
244
+ */
245
+ namespace NoOptionalPhantomProperty {
246
+ export type RuleEntry = Linter.StringSeverity;
247
+ }
248
+
235
249
  /**
236
250
  * @description Disallow a comment paragraph wrapped unevenly: a line with room for the first word of the line after it
237
251
  *
@@ -721,6 +735,7 @@ export type EslintTsRestrictionsRules = Readonly<{
721
735
  'ts-restrictions/no-detached-jsdoc': NoDetachedJsdoc.RuleEntry;
722
736
  'ts-restrictions/no-export-type-side-effects': NoExportTypeSideEffects.RuleEntry;
723
737
  'ts-restrictions/no-negated-comparison': NoNegatedComparison.RuleEntry;
738
+ 'ts-restrictions/no-optional-phantom-property': NoOptionalPhantomProperty.RuleEntry;
724
739
  'ts-restrictions/no-ragged-comment-wrap': NoRaggedCommentWrap.RuleEntry;
725
740
  'ts-restrictions/no-restricted-cast-name': NoRestrictedCastName.RuleEntry;
726
741
  'ts-restrictions/no-restricted-syntax': NoRestrictedSyntax.RuleEntry;