@definitelytyped/eslint-plugin 0.0.166-next.4

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 (121) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +5 -0
  3. package/dist/configs/all.d.ts +2 -0
  4. package/dist/configs/all.js +152 -0
  5. package/dist/configs/all.js.map +1 -0
  6. package/dist/index.d.ts +4 -0
  7. package/dist/index.js +10 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/rules/dt-header.d.ts +2 -0
  10. package/dist/rules/dt-header.js +62 -0
  11. package/dist/rules/dt-header.js.map +1 -0
  12. package/dist/rules/export-just-namespace.d.ts +2 -0
  13. package/dist/rules/export-just-namespace.js +70 -0
  14. package/dist/rules/export-just-namespace.js.map +1 -0
  15. package/dist/rules/index.d.ts +38 -0
  16. package/dist/rules/index.js +61 -0
  17. package/dist/rules/index.js.map +1 -0
  18. package/dist/rules/no-any-union.d.ts +4 -0
  19. package/dist/rules/no-any-union.js +34 -0
  20. package/dist/rules/no-any-union.js.map +1 -0
  21. package/dist/rules/no-bad-reference.d.ts +2 -0
  22. package/dist/rules/no-bad-reference.js +55 -0
  23. package/dist/rules/no-bad-reference.js.map +1 -0
  24. package/dist/rules/no-const-enum.d.ts +4 -0
  25. package/dist/rules/no-const-enum.js +30 -0
  26. package/dist/rules/no-const-enum.js.map +1 -0
  27. package/dist/rules/no-dead-reference.d.ts +2 -0
  28. package/dist/rules/no-dead-reference.js +44 -0
  29. package/dist/rules/no-dead-reference.js.map +1 -0
  30. package/dist/rules/no-declare-current-package.d.ts +4 -0
  31. package/dist/rules/no-declare-current-package.js +43 -0
  32. package/dist/rules/no-declare-current-package.js.map +1 -0
  33. package/dist/rules/no-import-default-of-export-equals.d.ts +4 -0
  34. package/dist/rules/no-import-default-of-export-equals.js +87 -0
  35. package/dist/rules/no-import-default-of-export-equals.js.map +1 -0
  36. package/dist/rules/no-outside-dependencies.d.ts +2 -0
  37. package/dist/rules/no-outside-dependencies.js +41 -0
  38. package/dist/rules/no-outside-dependencies.js.map +1 -0
  39. package/dist/rules/no-self-import.d.ts +4 -0
  40. package/dist/rules/no-self-import.js +38 -0
  41. package/dist/rules/no-self-import.js.map +1 -0
  42. package/dist/rules/no-single-element-tuple-type.d.ts +5 -0
  43. package/dist/rules/no-single-element-tuple-type.js +30 -0
  44. package/dist/rules/no-single-element-tuple-type.js.map +1 -0
  45. package/dist/rules/no-unnecessary-generics.d.ts +8 -0
  46. package/dist/rules/no-unnecessary-generics.js +135 -0
  47. package/dist/rules/no-unnecessary-generics.js.map +1 -0
  48. package/dist/rules/no-useless-files.d.ts +2 -0
  49. package/dist/rules/no-useless-files.js +53 -0
  50. package/dist/rules/no-useless-files.js.map +1 -0
  51. package/dist/rules/prefer-declare-function.d.ts +5 -0
  52. package/dist/rules/prefer-declare-function.js +35 -0
  53. package/dist/rules/prefer-declare-function.js.map +1 -0
  54. package/dist/rules/redundant-undefined.d.ts +4 -0
  55. package/dist/rules/redundant-undefined.js +53 -0
  56. package/dist/rules/redundant-undefined.js.map +1 -0
  57. package/dist/rules/trim-file.d.ts +2 -0
  58. package/dist/rules/trim-file.js +43 -0
  59. package/dist/rules/trim-file.js.map +1 -0
  60. package/dist/util.d.ts +4 -0
  61. package/dist/util.js +38 -0
  62. package/dist/util.js.map +1 -0
  63. package/docs/rules/dt-header.md +88 -0
  64. package/docs/rules/export-just-namespace.md +29 -0
  65. package/docs/rules/no-any-union.md +27 -0
  66. package/docs/rules/no-bad-reference.md +28 -0
  67. package/docs/rules/no-const-enum.md +16 -0
  68. package/docs/rules/no-dead-reference.md +17 -0
  69. package/docs/rules/no-declare-current-package.md +35 -0
  70. package/docs/rules/no-import-default-of-export-equals.md +22 -0
  71. package/docs/rules/no-outside-dependencies.md +23 -0
  72. package/docs/rules/no-self-import.md +27 -0
  73. package/docs/rules/no-single-element-tuple-type.md +15 -0
  74. package/docs/rules/no-unnecessary-generics.md +69 -0
  75. package/docs/rules/no-useless-files.md +14 -0
  76. package/docs/rules/prefer-declare-function.md +15 -0
  77. package/docs/rules/redundant-undefined.md +15 -0
  78. package/docs/rules/trim-file.md +17 -0
  79. package/package.json +45 -0
  80. package/src/configs/all.ts +151 -0
  81. package/src/index.ts +6 -0
  82. package/src/rules/dt-header.ts +74 -0
  83. package/src/rules/export-just-namespace.ts +83 -0
  84. package/src/rules/index.ts +35 -0
  85. package/src/rules/no-any-union.ts +34 -0
  86. package/src/rules/no-bad-reference.ts +62 -0
  87. package/src/rules/no-const-enum.ts +30 -0
  88. package/src/rules/no-dead-reference.ts +46 -0
  89. package/src/rules/no-declare-current-package.ts +45 -0
  90. package/src/rules/no-import-default-of-export-equals.ts +68 -0
  91. package/src/rules/no-outside-dependencies.ts +42 -0
  92. package/src/rules/no-self-import.ts +40 -0
  93. package/src/rules/no-single-element-tuple-type.ts +31 -0
  94. package/src/rules/no-unnecessary-generics.ts +126 -0
  95. package/src/rules/no-useless-files.ts +58 -0
  96. package/src/rules/prefer-declare-function.ts +37 -0
  97. package/src/rules/redundant-undefined.ts +62 -0
  98. package/src/rules/trim-file.ts +45 -0
  99. package/src/util.ts +41 -0
  100. package/test/dt-header.test.ts +189 -0
  101. package/test/export-just-namespace.test.ts +70 -0
  102. package/test/no-any-union.test.ts +22 -0
  103. package/test/no-bad-reference.test.ts +66 -0
  104. package/test/no-const-enum.test.ts +22 -0
  105. package/test/no-dead-reference.test.ts +66 -0
  106. package/test/no-declare-current-package.test.ts +61 -0
  107. package/test/no-import-default-of-export-equals.test.ts +49 -0
  108. package/test/no-self-import.test.ts +47 -0
  109. package/test/no-single-element-tuple-type.test.ts +28 -0
  110. package/test/no-unnecessary-generics.test.ts +152 -0
  111. package/test/no-useless-files.test.ts +42 -0
  112. package/test/prefer-declare-function.test.ts +66 -0
  113. package/test/redundant-undefined.test.ts +39 -0
  114. package/test/trim-file.test.ts +46 -0
  115. package/test/tsconfig.json +10 -0
  116. package/test/tsconfig.no-declare-current-package.json +11 -0
  117. package/test/tsconfig.no-declare-current-package2.json +11 -0
  118. package/test/tsconfig.no-import-default-of-export-equals.json +11 -0
  119. package/test/tsconfig.no-self-import.json +7 -0
  120. package/tsconfig.json +9 -0
  121. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,40 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ import { createRule, getCommonDirectoryName } from "../util";
3
+
4
+ const rule = createRule({
5
+ name: "no-self-import",
6
+ defaultOptions: [],
7
+ meta: {
8
+ type: "problem",
9
+ docs: {
10
+ description: "Forbids declaration files to import the current package using a global import.",
11
+ recommended: "error",
12
+ },
13
+ messages: {
14
+ useRelativeImport: "Declaration file should not use a global import of itself. Use a relative import.",
15
+ },
16
+ schema: [],
17
+ },
18
+ create(context) {
19
+ if (!context.getFilename().endsWith(".d.ts")) {
20
+ return {};
21
+ }
22
+
23
+ const services = ESLintUtils.getParserServices(context);
24
+ const packageName = getCommonDirectoryName(services.program.getRootFileNames());
25
+
26
+ return {
27
+ // eslint-disable-next-line @typescript-eslint/naming-convention
28
+ ImportDeclaration(node) {
29
+ if (node.source.value === packageName || node.source.value.startsWith(packageName + "/")) {
30
+ context.report({
31
+ messageId: "useRelativeImport",
32
+ node,
33
+ });
34
+ }
35
+ },
36
+ };
37
+ },
38
+ });
39
+
40
+ export = rule;
@@ -0,0 +1,31 @@
1
+ import { createRule } from "../util";
2
+ import { TSESTree } from "@typescript-eslint/utils";
3
+
4
+ const rule = createRule({
5
+ name: "no-single-element-tuple-type",
6
+ defaultOptions: [],
7
+ meta: {
8
+ type: "problem",
9
+ docs: {
10
+ description: "Forbids `[T]`, which should be `T[]`.",
11
+ recommended: "error",
12
+ },
13
+ messages: {
14
+ singleElementTupleType: `Type [T] is a single-element tuple type. You probably meant T[].`,
15
+ },
16
+ schema: [],
17
+ },
18
+ create(context) {
19
+ return {
20
+ // eslint-disable-next-line @typescript-eslint/naming-convention
21
+ "TSTupleType[elementTypes.length=1]"(node: TSESTree.TSTupleType) {
22
+ context.report({
23
+ messageId: "singleElementTupleType",
24
+ node,
25
+ });
26
+ },
27
+ };
28
+ },
29
+ });
30
+
31
+ export = rule;
@@ -0,0 +1,126 @@
1
+ import { ESLintUtils, TSESTree } from "@typescript-eslint/utils";
2
+ import * as ts from "typescript";
3
+
4
+ import { createRule } from "../util";
5
+
6
+ type ESTreeFunctionLikeWithTypeParameters = TSESTree.FunctionLike & {
7
+ typeParameters: {};
8
+ };
9
+
10
+ type TSSignatureDeclarationWithTypeParameters = ts.SignatureDeclaration & {
11
+ typeParameters: {};
12
+ };
13
+
14
+ const rule = createRule({
15
+ defaultOptions: [],
16
+ meta: {
17
+ docs: {
18
+ description: "Forbids signatures using a generic parameter only once.",
19
+ recommended: "error",
20
+ },
21
+ messages: {
22
+ never: "Type parameter {{name}} is never used.",
23
+ sole: "Type parameter {{name}} is used only once.",
24
+ },
25
+ schema: [],
26
+ type: "problem",
27
+ },
28
+ name: "no-relative-import-in-test",
29
+ create(context) {
30
+ return {
31
+ [[
32
+ "ArrowFunctionExpression[typeParameters]",
33
+ "FunctionDeclaration[typeParameters]",
34
+ "FunctionExpression[typeParameters]",
35
+ "TSCallSignatureDeclaration[typeParameters]",
36
+ "TSConstructorType[typeParameters]",
37
+ "TSDeclareFunction[typeParameters]",
38
+ "TSFunctionType[typeParameters]",
39
+ "TSMethodSignature[typeParameters]",
40
+ ].join(", ")](esNode: ESTreeFunctionLikeWithTypeParameters) {
41
+ const parserServices = ESLintUtils.getParserServices(context);
42
+ const tsNode = parserServices.esTreeNodeToTSNodeMap.get(esNode) as TSSignatureDeclarationWithTypeParameters;
43
+ if (!tsNode.typeParameters) {
44
+ return;
45
+ }
46
+
47
+ const checker = parserServices.program.getTypeChecker();
48
+
49
+ for (const typeParameter of tsNode.typeParameters) {
50
+ const name = typeParameter.name.text;
51
+ const res = getSoleUse(tsNode, assertDefined(checker.getSymbolAtLocation(typeParameter.name)), checker);
52
+ switch (res.type) {
53
+ case "sole":
54
+ context.report({
55
+ data: { name },
56
+ messageId: "sole",
57
+ node: parserServices.tsNodeToESTreeNodeMap.get(res.soleUse),
58
+ });
59
+ break;
60
+ case "never":
61
+ context.report({
62
+ data: { name },
63
+ messageId: "never",
64
+ node: parserServices.tsNodeToESTreeNodeMap.get(typeParameter),
65
+ });
66
+ break;
67
+ }
68
+ }
69
+ },
70
+ };
71
+ },
72
+ });
73
+
74
+ type Result = { type: "ok" | "never" } | { type: "sole"; soleUse: ts.Identifier };
75
+ function getSoleUse(sig: ts.SignatureDeclaration, typeParameterSymbol: ts.Symbol, checker: ts.TypeChecker): Result {
76
+ const exit = {};
77
+ let soleUse: ts.Identifier | undefined;
78
+
79
+ try {
80
+ if (sig.typeParameters) {
81
+ for (const tp of sig.typeParameters) {
82
+ if (tp.constraint) {
83
+ recur(tp.constraint);
84
+ }
85
+ }
86
+ }
87
+ for (const param of sig.parameters) {
88
+ if (param.type) {
89
+ recur(param.type);
90
+ }
91
+ }
92
+ if (sig.type) {
93
+ recur(sig.type);
94
+ }
95
+ } catch (err) {
96
+ if (err === exit) {
97
+ return { type: "ok" };
98
+ }
99
+ throw err;
100
+ }
101
+
102
+ return soleUse ? { type: "sole", soleUse } : { type: "never" };
103
+
104
+ function recur(node: ts.Node): void {
105
+ if (ts.isIdentifier(node)) {
106
+ if (checker.getSymbolAtLocation(node) === typeParameterSymbol) {
107
+ if (soleUse === undefined) {
108
+ soleUse = node;
109
+ } else {
110
+ throw exit;
111
+ }
112
+ }
113
+ } else {
114
+ node.forEachChild(recur);
115
+ }
116
+ }
117
+ }
118
+
119
+ export = rule;
120
+
121
+ function assertDefined<T>(value: T | undefined): T {
122
+ if (value === undefined) {
123
+ throw new Error("unreachable");
124
+ }
125
+ return value;
126
+ }
@@ -0,0 +1,58 @@
1
+ import { createRule } from "../util";
2
+
3
+ const rule = createRule({
4
+ name: "no-useless-files",
5
+ defaultOptions: [],
6
+ meta: {
7
+ type: "problem",
8
+ docs: {
9
+ description: "Forbids files with no content.",
10
+ recommended: "error",
11
+ },
12
+ messages: {
13
+ noContent: "File has no content.",
14
+ },
15
+ schema: [],
16
+ },
17
+ create(context) {
18
+ const {
19
+ ast: { tokens, comments },
20
+ } = context.getSourceCode();
21
+
22
+ if (tokens.length === 0) {
23
+ if (comments.length === 0) {
24
+ reportNoContent();
25
+ } else {
26
+ const referenceRegExp = /^\/\s*<reference\s*(types|path)\s*=\s*["|'](.*)["|']/;
27
+ let noReferenceFound = true;
28
+
29
+ for (const comment of comments) {
30
+ const referenceMatch = comment.value.match(referenceRegExp)?.[1];
31
+ if (!referenceMatch) {
32
+ continue;
33
+ }
34
+ noReferenceFound = false;
35
+ break;
36
+ }
37
+
38
+ if (noReferenceFound) {
39
+ reportNoContent();
40
+ }
41
+ }
42
+ }
43
+
44
+ return {};
45
+
46
+ function reportNoContent() {
47
+ context.report({
48
+ messageId: "noContent",
49
+ loc: {
50
+ start: { line: 1, column: 0 },
51
+ end: { line: 1, column: 0 },
52
+ },
53
+ });
54
+ }
55
+ },
56
+ });
57
+
58
+ export = rule;
@@ -0,0 +1,37 @@
1
+ import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/utils";
2
+
3
+ import { createRule } from "../util";
4
+
5
+ const rule = createRule({
6
+ defaultOptions: [],
7
+ meta: {
8
+ docs: {
9
+ description: "Forbids `const x: () => void`.",
10
+ recommended: "error",
11
+ },
12
+ messages: {
13
+ variableFunction: "Use a function declaration instead of a variable of function type.",
14
+ },
15
+ schema: [],
16
+ type: "problem",
17
+ },
18
+ name: "prefer-declare-function",
19
+ create(context) {
20
+ return {
21
+ // eslint-disable-next-line @typescript-eslint/naming-convention
22
+ "VariableDeclaration > VariableDeclarator"(node: TSESTree.VariableDeclarator) {
23
+ if (
24
+ node.id.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES.TSFunctionType &&
25
+ context.getFilename().endsWith(".d.ts")
26
+ ) {
27
+ context.report({
28
+ messageId: "variableFunction",
29
+ node: node.id,
30
+ });
31
+ }
32
+ },
33
+ };
34
+ },
35
+ });
36
+
37
+ export = rule;
@@ -0,0 +1,62 @@
1
+ import { createRule } from "../util";
2
+ import { AST_NODE_TYPES } from "@typescript-eslint/utils";
3
+ import { TSESTree } from "@typescript-eslint/types";
4
+
5
+ const rule = createRule({
6
+ name: "redundant-undefined",
7
+ defaultOptions: [],
8
+ meta: {
9
+ type: "problem",
10
+ docs: {
11
+ description:
12
+ "Forbids optional parameters from including an explicit `undefined` in their type; requires it in optional properties.",
13
+ recommended: "error",
14
+ },
15
+ messages: {
16
+ redundantUndefined: `Parameter is optional, so no need to include \`undefined\` in the type.`,
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ // eslint-disable-next-line @typescript-eslint/naming-convention
23
+ TSUnionType(node) {
24
+ const hasUndefinedType = node.types.some((t) => t.type === AST_NODE_TYPES.TSUndefinedKeyword);
25
+ if (
26
+ node.parent!.type === AST_NODE_TYPES.TSTypeAnnotation &&
27
+ isParameter(node.parent!.parent!) &&
28
+ node.parent.parent.optional &&
29
+ isFunctionLike(node.parent!.parent!.parent!) &&
30
+ hasUndefinedType
31
+ ) {
32
+ context.report({
33
+ messageId: "redundantUndefined",
34
+ node,
35
+ });
36
+ }
37
+ },
38
+ };
39
+ },
40
+ });
41
+
42
+ function isFunctionLike(node: TSESTree.Node): node is TSESTree.FunctionLike {
43
+ return (
44
+ node.type === AST_NODE_TYPES.ArrowFunctionExpression ||
45
+ node.type === AST_NODE_TYPES.FunctionDeclaration ||
46
+ node.type === AST_NODE_TYPES.FunctionExpression ||
47
+ node.type === AST_NODE_TYPES.TSDeclareFunction ||
48
+ node.type === AST_NODE_TYPES.TSEmptyBodyFunctionExpression
49
+ );
50
+ }
51
+ /** Note: Does not include parameter properties because those can't be optional */
52
+ function isParameter(node: TSESTree.Node): node is Exclude<TSESTree.Parameter, TSESTree.TSParameterProperty> {
53
+ return (
54
+ node.type === AST_NODE_TYPES.ArrayPattern ||
55
+ node.type === AST_NODE_TYPES.AssignmentPattern ||
56
+ node.type === AST_NODE_TYPES.Identifier ||
57
+ node.type === AST_NODE_TYPES.ObjectPattern ||
58
+ node.type === AST_NODE_TYPES.RestElement
59
+ );
60
+ }
61
+
62
+ export = rule;
@@ -0,0 +1,45 @@
1
+ import { createRule } from "../util";
2
+
3
+ const rule = createRule({
4
+ name: "trim-file",
5
+ defaultOptions: [],
6
+ meta: {
7
+ type: "layout",
8
+ docs: {
9
+ description: "Forbids leading/trailing blank lines in a file. Allows file to end in '\n'",
10
+ recommended: "error",
11
+ },
12
+ messages: {
13
+ leadingBlankLine: "File should not begin with a blank line.",
14
+ trailingBlankLine:
15
+ "File should not end with a blank line. (Ending in one newline OK, ending in two newlines not OK.)",
16
+ },
17
+ schema: [],
18
+ },
19
+ create(context) {
20
+ const { lines, text } = context.getSourceCode();
21
+ if (text.startsWith("\r") || text.startsWith("\n")) {
22
+ context.report({
23
+ messageId: "leadingBlankLine",
24
+ loc: {
25
+ start: { line: 1, column: 0 },
26
+ end: { line: 1, column: 0 },
27
+ },
28
+ });
29
+ }
30
+ if (text.endsWith("\n\n") || text.endsWith("\r\n\r\n")) {
31
+ const line = lines.length;
32
+ context.report({
33
+ messageId: "trailingBlankLine",
34
+ loc: {
35
+ start: { line, column: 0 },
36
+ end: { line, column: 0 },
37
+ },
38
+ });
39
+ }
40
+
41
+ return {};
42
+ },
43
+ });
44
+
45
+ export = rule;
package/src/util.ts ADDED
@@ -0,0 +1,41 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ import { basename, dirname } from "path";
3
+
4
+ export const createRule = ESLintUtils.RuleCreator(
5
+ (name) =>
6
+ `https://github.com/microsoft/DefinitelyTyped-tools/tree/master/packages/eslint-plugin/docs/rules/${name}.md`
7
+ );
8
+
9
+ export function getCommonDirectoryName(files: readonly string[]): string {
10
+ let minLen = 999;
11
+ let minDir = "";
12
+ for (const file of files) {
13
+ const dir = dirname(file);
14
+ if (dir.length < minLen) {
15
+ minDir = dir;
16
+ minLen = dir.length;
17
+ }
18
+ }
19
+ return basename(minDir);
20
+ }
21
+
22
+ export function isMainFile(fileName: string, allowNested: boolean) {
23
+ // Linter may be run with cwd of the package. We want `index.d.ts` but not `submodule/index.d.ts` to match.
24
+ if (fileName === "index.d.ts") {
25
+ return true;
26
+ }
27
+
28
+ if (basename(fileName) !== "index.d.ts") {
29
+ return false;
30
+ }
31
+
32
+ let parent = dirname(fileName);
33
+ // May be a directory for an older version, e.g. `v0`.
34
+ // Note a types redirect `foo/ts3.1` should not have its own header.
35
+ if (allowNested && /^v(0\.)?\d+$/.test(basename(parent))) {
36
+ parent = dirname(parent);
37
+ }
38
+
39
+ // Allow "types/foo/index.d.ts", not "types/foo/utils/index.d.ts"
40
+ return basename(dirname(parent)) === "types";
41
+ }
@@ -0,0 +1,189 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+
3
+ import * as dtHeader from "../src/rules/dt-header";
4
+
5
+ const ruleTester = new ESLintUtils.RuleTester({
6
+ parser: "@typescript-eslint/parser",
7
+ });
8
+
9
+ ruleTester.run("@definitelytyped/dt-header", dtHeader, {
10
+ invalid: [
11
+ {
12
+ code: ``,
13
+ errors: [
14
+ {
15
+ column: 2,
16
+ data: {
17
+ expected: "/\\/\\/ Type definitions for (non-npm package )?/",
18
+ },
19
+ line: 1,
20
+ messageId: "parseError",
21
+ },
22
+ ],
23
+ filename: "types/blank/index.d.ts",
24
+ },
25
+ {
26
+ code: `
27
+ // ...
28
+ `,
29
+ errors: [
30
+ {
31
+ column: 1,
32
+ data: {
33
+ expected: "/\\/\\/ Type definitions for (non-npm package )?/",
34
+ },
35
+ line: 2,
36
+ messageId: "parseError",
37
+ },
38
+ ],
39
+ filename: "types/only-comment/index.d.ts",
40
+ },
41
+ {
42
+ code: `
43
+ // Type definitions for dt-header 0.75
44
+ // Project: https://github.com/bobby-headers/dt-header
45
+ // Definitions by: Jane Doe <https://github.com/janedoe>
46
+ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
47
+ // Minimum TypeScript Version: 3.1
48
+
49
+ `,
50
+ errors: [
51
+ {
52
+ column: 1,
53
+ data: {
54
+ expected: "/\\/\\/ Type definitions for (non-npm package )?/",
55
+ },
56
+ line: 2,
57
+ messageId: "parseError",
58
+ },
59
+ ],
60
+ filename: "types/start-with-whitespace/index.d.ts",
61
+ },
62
+ {
63
+ code: `// Type definitions for dt-header 1.0
64
+ // Project: https://github.com/bobby-headers/dt-header
65
+ // Definitions by: Jane Doe <https://github.ORG/janedoe>
66
+ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
67
+ `,
68
+ errors: [
69
+ {
70
+ column: 30,
71
+ data: {
72
+ expected: "/\\<https\\:\\/\\/github\\.com\\/([a-zA-Z\\d\\-]+)\\/?\\>/",
73
+ },
74
+ line: 3,
75
+ messageId: "parseError",
76
+ },
77
+ ],
78
+ filename: "types/bad-url-github-org/index.d.ts",
79
+ },
80
+ {
81
+ code: `// Type definitions for dt-header 1.0
82
+ // Project: https://github.com/bobby-headers/dt-header
83
+ // Definitions by: Jane Doe <https://github.com/jane doe>
84
+ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
85
+ `,
86
+ errors: [
87
+ {
88
+ column: 30,
89
+ data: {
90
+ expected: "/\\<https\\:\\/\\/github\\.com\\/([a-zA-Z\\d\\-]+)\\/?\\>/",
91
+ },
92
+ line: 3,
93
+ messageId: "parseError",
94
+ },
95
+ ],
96
+ filename: "types/bad-url-space/index.d.ts",
97
+ },
98
+ {
99
+ code: `// Type definitions for dt-header 1.0
100
+ // Project: https://github.com/not/important
101
+ // Definitions by: My Self <https://github.com/me>
102
+ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
103
+
104
+ `,
105
+ errors: [
106
+ {
107
+ column: 1,
108
+ endColumn: 27,
109
+ line: 3,
110
+ messageId: "definitionsBy",
111
+ },
112
+ ],
113
+ filename: "types/bad-username/index.d.ts",
114
+ },
115
+ {
116
+ code: `// Type definitions for dt-header v1.0.3
117
+ // Project: https://github.com/bobby-headers/dt-header
118
+ // Definitions by: Jane Doe <https://github.com/janedoe>
119
+ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
120
+ `,
121
+ errors: [
122
+ {
123
+ column: 26,
124
+ data: {
125
+ expected: "foo MAJOR.MINOR (patch version not allowed)",
126
+ },
127
+ line: 1,
128
+ messageId: "parseError",
129
+ },
130
+ ],
131
+ filename: "types/foo/index.d.ts",
132
+ },
133
+ {
134
+ code: `// Type definitions for
135
+ `,
136
+ errors: [
137
+ {
138
+ column: 1,
139
+ endColumn: 24,
140
+ line: 1,
141
+ messageId: "typeDefinitionsFor",
142
+ },
143
+ ],
144
+ filename: "types/foo/notIndex.d.ts",
145
+ },
146
+ ],
147
+ valid: [
148
+ ``,
149
+ {
150
+ code: `// This isn't the main index
151
+ `,
152
+ filename: "types/foo/bar/index.d.ts",
153
+ },
154
+ {
155
+ code: `// Type definitions for dt-header 0.75
156
+ // Project: https://github.com/bobby-headers/dt-header
157
+ // Definitions by: Jane Doe <https://github.com/janedoe>
158
+ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
159
+ // Minimum TypeScript Version: 3.1
160
+
161
+ `,
162
+ filename: "types/foo/v0.75/index.d.ts",
163
+ },
164
+ {
165
+ code: `// Type definitions for dt-header 1.0
166
+ // Project: https://github.com/bobby-headers/dt-header
167
+ // Definitions by: Jane Doe <https://github.com/janedoe>
168
+ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
169
+ // Minimum TypeScript Version: 3.1
170
+
171
+ `,
172
+ filename: "types/foo/v1/index.d.ts",
173
+ },
174
+ {
175
+ code: `// Type definitions for dt-header 2.0
176
+ // Project: https://github.com/bobby-headers/dt-header
177
+ // Definitions by: Jane Doe <https://github.com/janedoe>
178
+ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
179
+ // Minimum TypeScript Version: 3.1
180
+
181
+ `,
182
+ filename: "types/foo/index.d.ts",
183
+ },
184
+ {
185
+ code: ``,
186
+ filename: "types/foo/notIndex.d.ts",
187
+ },
188
+ ],
189
+ });
@@ -0,0 +1,70 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+
3
+ import * as exportJustNamespace from "../src/rules/export-just-namespace";
4
+
5
+ const ruleTester = new ESLintUtils.RuleTester({
6
+ parser: "@typescript-eslint/parser",
7
+ });
8
+
9
+ ruleTester.run("@definitelytyped/export-just-namespace", exportJustNamespace, {
10
+ invalid: [
11
+ {
12
+ code: `
13
+ export = Stuff;
14
+ namespace Stuff {}
15
+ `,
16
+ errors: [
17
+ {
18
+ line: 2,
19
+ messageId: "useTheBody",
20
+ },
21
+ ],
22
+ },
23
+ {
24
+ code: `
25
+ namespace Stuff {}
26
+ export = Stuff;
27
+ `,
28
+ errors: [
29
+ {
30
+ line: 3,
31
+ messageId: "useTheBody",
32
+ },
33
+ ],
34
+ },
35
+ {
36
+ code: `
37
+ namespace Stuff {}
38
+ const other = "code";
39
+ export = Stuff;
40
+ `,
41
+ errors: [
42
+ {
43
+ line: 4,
44
+ messageId: "useTheBody",
45
+ },
46
+ ],
47
+ },
48
+ ],
49
+ valid: [
50
+ `export const value = 3;`,
51
+ `export default class Hello {}`,
52
+ 'import * as fs from "fs";',
53
+ "const value = 123;",
54
+ `export = stuff;`,
55
+ `export = createStuff();`,
56
+ `
57
+ class Stuff {}
58
+ namespace Stuff {}
59
+ export = Stuff;
60
+ `,
61
+ `export = First
62
+ namespace First {}
63
+ declare function First()
64
+ `,
65
+ `declare namespace Second {}
66
+ export = Second
67
+ declare function Second<U, S>(s: U): S
68
+ `,
69
+ ],
70
+ });