@flint.fyi/ts 0.14.3 → 0.14.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 (101) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/lib/createTypeScriptFileFromProgram.js +1 -0
  3. package/lib/language.d.ts +1 -0
  4. package/lib/plugin.d.ts +44 -0
  5. package/lib/plugin.js +22 -0
  6. package/lib/rules/anyReturns.d.ts +6 -0
  7. package/lib/rules/anyReturns.js +187 -0
  8. package/lib/rules/anyReturns.test.d.ts +1 -0
  9. package/lib/rules/anyReturns.test.js +647 -0
  10. package/lib/rules/caseDuplicates.d.ts +6 -0
  11. package/lib/rules/caseDuplicates.js +49 -0
  12. package/lib/rules/caseDuplicates.test.d.ts +1 -0
  13. package/lib/rules/caseDuplicates.test.js +307 -0
  14. package/lib/rules/elseIfDuplicates.d.ts +6 -0
  15. package/lib/rules/elseIfDuplicates.js +53 -0
  16. package/lib/rules/elseIfDuplicates.test.d.ts +1 -0
  17. package/lib/rules/elseIfDuplicates.test.js +176 -0
  18. package/lib/rules/forDirections.d.ts +6 -0
  19. package/lib/rules/forDirections.js +124 -0
  20. package/lib/rules/forDirections.test.d.ts +1 -0
  21. package/lib/rules/forDirections.test.js +99 -0
  22. package/lib/rules/functionNewCalls.d.ts +6 -0
  23. package/lib/rules/functionNewCalls.js +60 -0
  24. package/lib/rules/functionNewCalls.test.d.ts +1 -0
  25. package/lib/rules/functionNewCalls.test.js +115 -0
  26. package/lib/rules/negativeZeroComparisons.js +4 -22
  27. package/lib/rules/nonOctalDecimalEscapes.d.ts +6 -0
  28. package/lib/rules/nonOctalDecimalEscapes.js +57 -0
  29. package/lib/rules/nonOctalDecimalEscapes.test.d.ts +1 -0
  30. package/lib/rules/nonOctalDecimalEscapes.test.js +69 -0
  31. package/lib/rules/numericLiteralParsing.d.ts +6 -0
  32. package/lib/rules/numericLiteralParsing.js +97 -0
  33. package/lib/rules/numericLiteralParsing.test.d.ts +1 -0
  34. package/lib/rules/numericLiteralParsing.test.js +99 -0
  35. package/lib/rules/selfAssignments.d.ts +6 -0
  36. package/lib/rules/selfAssignments.js +44 -0
  37. package/lib/rules/selfAssignments.test.d.ts +1 -0
  38. package/lib/rules/selfAssignments.test.js +66 -0
  39. package/lib/rules/selfComparisons.d.ts +6 -0
  40. package/lib/rules/selfComparisons.js +41 -0
  41. package/lib/rules/selfComparisons.test.d.ts +1 -0
  42. package/lib/rules/selfComparisons.test.js +297 -0
  43. package/lib/rules/sequences.d.ts +6 -0
  44. package/lib/rules/sequences.js +34 -0
  45. package/lib/rules/sequences.test.d.ts +1 -0
  46. package/lib/rules/sequences.test.js +48 -0
  47. package/lib/rules/typeofComparisons.d.ts +6 -0
  48. package/lib/rules/typeofComparisons.js +78 -0
  49. package/lib/rules/typeofComparisons.test.d.ts +1 -0
  50. package/lib/rules/typeofComparisons.test.js +85 -0
  51. package/lib/rules/utils/discriminateAnyType.d.ts +12 -0
  52. package/lib/rules/utils/discriminateAnyType.js +41 -0
  53. package/lib/rules/utils/getThisExpression.d.ts +2 -0
  54. package/lib/rules/utils/getThisExpression.js +23 -0
  55. package/lib/rules/utils/isUnsafeAssignment.d.ts +13 -0
  56. package/lib/rules/utils/isUnsafeAssignment.js +76 -0
  57. package/lib/rules/utils/operators.d.ts +4 -0
  58. package/lib/rules/utils/operators.js +36 -0
  59. package/lib/utils/declarationIncludesGlobal.d.ts +2 -0
  60. package/lib/utils/declarationIncludesGlobal.js +5 -0
  61. package/lib/utils/declarationsIncludeGlobal.js +2 -5
  62. package/lib/utils/hasSameTokens.d.ts +2 -0
  63. package/lib/utils/hasSameTokens.js +30 -0
  64. package/lib/utils/isGlobalDeclarationOfName.d.ts +5 -0
  65. package/lib/utils/isGlobalDeclarationOfName.js +31 -0
  66. package/package.json +1 -1
  67. package/src/createTypeScriptFileFromProgram.ts +1 -0
  68. package/src/language.ts +1 -0
  69. package/src/plugin.ts +22 -0
  70. package/src/rules/anyReturns.test.ts +649 -0
  71. package/src/rules/anyReturns.ts +263 -0
  72. package/src/rules/caseDuplicates.test.ts +308 -0
  73. package/src/rules/caseDuplicates.ts +57 -0
  74. package/src/rules/elseIfDuplicates.test.ts +177 -0
  75. package/src/rules/elseIfDuplicates.ts +69 -0
  76. package/src/rules/forDirections.test.ts +100 -0
  77. package/src/rules/forDirections.ts +163 -0
  78. package/src/rules/functionNewCalls.test.ts +116 -0
  79. package/src/rules/functionNewCalls.ts +75 -0
  80. package/src/rules/negativeZeroComparisons.ts +8 -27
  81. package/src/rules/nonOctalDecimalEscapes.test.ts +70 -0
  82. package/src/rules/nonOctalDecimalEscapes.ts +70 -0
  83. package/src/rules/numericLiteralParsing.test.ts +100 -0
  84. package/src/rules/numericLiteralParsing.ts +116 -0
  85. package/src/rules/selfAssignments.test.ts +67 -0
  86. package/src/rules/selfAssignments.ts +50 -0
  87. package/src/rules/selfComparisons.test.ts +298 -0
  88. package/src/rules/selfComparisons.ts +45 -0
  89. package/src/rules/sequences.test.ts +49 -0
  90. package/src/rules/sequences.ts +37 -0
  91. package/src/rules/typeofComparisons.test.ts +86 -0
  92. package/src/rules/typeofComparisons.ts +88 -0
  93. package/src/rules/utils/discriminateAnyType.ts +66 -0
  94. package/src/rules/utils/getThisExpression.ts +24 -0
  95. package/src/rules/utils/isUnsafeAssignment.ts +113 -0
  96. package/src/rules/utils/operators.ts +39 -0
  97. package/src/utils/declarationIncludesGlobal.ts +9 -0
  98. package/src/utils/declarationsIncludeGlobal.ts +3 -7
  99. package/src/utils/hasSameTokens.ts +45 -0
  100. package/src/utils/isGlobalDeclarationOfName.ts +51 -0
  101. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,647 @@
1
+ import rule from "./anyReturns.js";
2
+ import { ruleTester } from "./ruleTester.js";
3
+ ruleTester.describe(rule, {
4
+ invalid: [
5
+ {
6
+ code: `
7
+ function foo() {
8
+ return 1 as any;
9
+ }
10
+ `,
11
+ snapshot: `
12
+ function foo() {
13
+ return 1 as any;
14
+ ~~~~~~~~~~~~~~~~
15
+ Unsafe return of a value of type \`any\`.
16
+ }
17
+ `,
18
+ },
19
+ {
20
+ code: `
21
+ function foo() {
22
+ return Object.create(null);
23
+ }
24
+ `,
25
+ snapshot: `
26
+ function foo() {
27
+ return Object.create(null);
28
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
29
+ Unsafe return of a value of type \`any\`.
30
+ }
31
+ `,
32
+ },
33
+ {
34
+ code: `
35
+ const foo = () => {
36
+ return 1 as any;
37
+ };
38
+ `,
39
+ snapshot: `
40
+ const foo = () => {
41
+ return 1 as any;
42
+ ~~~~~~~~~~~~~~~~
43
+ Unsafe return of a value of type \`any\`.
44
+ };
45
+ `,
46
+ },
47
+ {
48
+ code: `
49
+ const foo = () => Object.create(null);'
50
+ `,
51
+ snapshot: `
52
+ const foo = () => Object.create(null);'
53
+ ~~~~~~~~~~~~~~~~~~~
54
+ Unsafe return of a value of type \`any\`.
55
+ `,
56
+ },
57
+ {
58
+ code: `
59
+ function foo() {
60
+ return [] as any[];
61
+ }
62
+ `,
63
+ snapshot: `
64
+ function foo() {
65
+ return [] as any[];
66
+ ~~~~~~~~~~~~~~~~~~~
67
+ Unsafe return of a value of type \`any[]\`.
68
+ }
69
+ `,
70
+ },
71
+ {
72
+ code: `
73
+ function foo() {
74
+ return [] as Array<any>;
75
+ }
76
+ `,
77
+ snapshot: `
78
+ function foo() {
79
+ return [] as Array<any>;
80
+ ~~~~~~~~~~~~~~~~~~~~~~~~
81
+ Unsafe return of a value of type \`any[]\`.
82
+ }
83
+ `,
84
+ },
85
+ {
86
+ code: `
87
+ function foo() {
88
+ return [] as readonly any[];
89
+ }
90
+ `,
91
+ snapshot: `
92
+ function foo() {
93
+ return [] as readonly any[];
94
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
95
+ Unsafe return of a value of type \`any[]\`.
96
+ }
97
+ `,
98
+ },
99
+ {
100
+ code: `
101
+ function foo() {
102
+ return [] as Readonly<any[]>;
103
+ }
104
+ `,
105
+ snapshot: `
106
+ function foo() {
107
+ return [] as Readonly<any[]>;
108
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
109
+ Unsafe return of a value of type \`any[]\`.
110
+ }
111
+ `,
112
+ },
113
+ {
114
+ code: `
115
+ const foo = () => {
116
+ return [] as any[];
117
+ };
118
+ `,
119
+ snapshot: `
120
+ const foo = () => {
121
+ return [] as any[];
122
+ ~~~~~~~~~~~~~~~~~~~
123
+ Unsafe return of a value of type \`any[]\`.
124
+ };
125
+ `,
126
+ },
127
+ {
128
+ code: `
129
+ const foo = () => [] as any[];
130
+ `,
131
+ snapshot: `
132
+ const foo = () => [] as any[];
133
+ ~~~~~~~~~~~
134
+ Unsafe return of a value of type \`any[]\`.
135
+ `,
136
+ },
137
+ {
138
+ code: `
139
+ function foo(): Set<string> {
140
+ return new Set<any>();
141
+ }
142
+ `,
143
+ snapshot: `
144
+ function foo(): Set<string> {
145
+ return new Set<any>();
146
+ ~~~~~~~~~~~~~~~~~~~~~~
147
+ Unsafe return of type \`Set<any>\` from function with return type \`Set<string>\`.
148
+ }
149
+ `,
150
+ },
151
+ {
152
+ code: `
153
+ function foo(): Map<string, string> {
154
+ return new Map<string, any>();
155
+ }
156
+ `,
157
+ snapshot: `
158
+ function foo(): Map<string, string> {
159
+ return new Map<string, any>();
160
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
161
+ Unsafe return of type \`Map<string, any>\` from function with return type \`Map<string, string>\`.
162
+ }
163
+ `,
164
+ },
165
+ {
166
+ code: `
167
+ function foo(): Set<string[]> {
168
+ return new Set<any[]>();
169
+ }
170
+ `,
171
+ snapshot: `
172
+ function foo(): Set<string[]> {
173
+ return new Set<any[]>();
174
+ ~~~~~~~~~~~~~~~~~~~~~~~~
175
+ Unsafe return of type \`Set<any[]>\` from function with return type \`Set<string[]>\`.
176
+ }
177
+ `,
178
+ },
179
+ {
180
+ code: `
181
+ function foo(): Set<Set<Set<string>>> {
182
+ return new Set<Set<Set<any>>>();
183
+ }
184
+ `,
185
+ snapshot: `
186
+ function foo(): Set<Set<Set<string>>> {
187
+ return new Set<Set<Set<any>>>();
188
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
189
+ Unsafe return of type \`Set<Set<Set<any>>>\` from function with return type \`Set<Set<Set<string>>>\`.
190
+ }
191
+ `,
192
+ },
193
+ {
194
+ code: `
195
+ type Fn = () => Set<string>;
196
+ const foo1: Fn = () => new Set<any>();
197
+ const foo2: Fn = function test() {
198
+ return new Set<any>();
199
+ };
200
+ `,
201
+ snapshot: `
202
+ type Fn = () => Set<string>;
203
+ const foo1: Fn = () => new Set<any>();
204
+ ~~~~~~~~~~~~~~
205
+ Unsafe return of type \`Set<any>\` from function with return type \`Set<string>\`.
206
+ const foo2: Fn = function test() {
207
+ return new Set<any>();
208
+ ~~~~~~~~~~~~~~~~~~~~~~
209
+ Unsafe return of type \`Set<any>\` from function with return type \`Set<string>\`.
210
+ };
211
+ `,
212
+ },
213
+ {
214
+ code: `
215
+ type Fn = () => Set<string>;
216
+ function receiver(arg: Fn) {}
217
+ receiver(() => new Set<any>());
218
+ receiver(function test() {
219
+ return new Set<any>();
220
+ });
221
+ `,
222
+ snapshot: `
223
+ type Fn = () => Set<string>;
224
+ function receiver(arg: Fn) {}
225
+ receiver(() => new Set<any>());
226
+ ~~~~~~~~~~~~~~
227
+ Unsafe return of type \`Set<any>\` from function with return type \`Set<string>\`.
228
+ receiver(function test() {
229
+ return new Set<any>();
230
+ ~~~~~~~~~~~~~~~~~~~~~~
231
+ Unsafe return of type \`Set<any>\` from function with return type \`Set<string>\`.
232
+ });
233
+ `,
234
+ },
235
+ {
236
+ code: `
237
+ function foo() {
238
+ return this;
239
+ }
240
+
241
+ function bar() {
242
+ return () => this;
243
+ }
244
+ `,
245
+ snapshot: `
246
+ function foo() {
247
+ return this;
248
+ ~~~~~~~~~~~~
249
+ Unsafe return of a value of type \`any\`.
250
+ }
251
+
252
+ function bar() {
253
+ return () => this;
254
+ ~~~~
255
+ Unsafe return of a value of type \`any\`.
256
+ }
257
+ `,
258
+ },
259
+ {
260
+ code: `
261
+ declare function foo(arg: null | (() => any)): void;
262
+ foo(() => 'foo' as any);
263
+ `,
264
+ snapshot: `
265
+ declare function foo(arg: null | (() => any)): void;
266
+ foo(() => 'foo' as any);
267
+ ~~~~~~~~~~~~
268
+ Unsafe return of a value of type \`any\`.
269
+ `,
270
+ },
271
+ {
272
+ code: `
273
+ let value: NotKnown;
274
+
275
+ function example() {
276
+ return value;
277
+ }
278
+ `,
279
+ snapshot: `
280
+ let value: NotKnown;
281
+
282
+ function example() {
283
+ return value;
284
+ ~~~~~~~~~~~~~
285
+ Unsafe return of a value of type error.
286
+ }
287
+ `,
288
+ },
289
+ {
290
+ code: `
291
+ declare const value: any;
292
+ async function foo() {
293
+ return value;
294
+ }
295
+ `,
296
+ snapshot: `
297
+ declare const value: any;
298
+ async function foo() {
299
+ return value;
300
+ ~~~~~~~~~~~~~
301
+ Unsafe return of a value of type \`any\`.
302
+ }
303
+ `,
304
+ },
305
+ {
306
+ code: `
307
+ declare const value: Promise<any>;
308
+ async function foo(): Promise<number> {
309
+ return value;
310
+ }
311
+ `,
312
+ snapshot: `
313
+ declare const value: Promise<any>;
314
+ async function foo(): Promise<number> {
315
+ return value;
316
+ ~~~~~~~~~~~~~
317
+ Unsafe return of a value of type \`Promise<any>\`.
318
+ }
319
+ `,
320
+ },
321
+ {
322
+ code: `
323
+ async function foo(arg: number) {
324
+ return arg as Promise<any>;
325
+ }
326
+ `,
327
+ snapshot: `
328
+ async function foo(arg: number) {
329
+ return arg as Promise<any>;
330
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
331
+ Unsafe return of a value of type \`Promise<any>\`.
332
+ }
333
+ `,
334
+ },
335
+ {
336
+ code: `
337
+ function foo(): Promise<any> {
338
+ return {} as any;
339
+ }
340
+ `,
341
+ snapshot: `
342
+ function foo(): Promise<any> {
343
+ return {} as any;
344
+ ~~~~~~~~~~~~~~~~~
345
+ Unsafe return of a value of type \`any\`.
346
+ }
347
+ `,
348
+ },
349
+ {
350
+ code: `
351
+ function foo(): Promise<object> {
352
+ return {} as any;
353
+ }
354
+ `,
355
+ snapshot: `
356
+ function foo(): Promise<object> {
357
+ return {} as any;
358
+ ~~~~~~~~~~~~~~~~~
359
+ Unsafe return of a value of type \`any\`.
360
+ }
361
+ `,
362
+ },
363
+ {
364
+ code: `
365
+ async function foo(): Promise<object> {
366
+ return Promise.resolve<any>({});
367
+ }
368
+ `,
369
+ snapshot: `
370
+ async function foo(): Promise<object> {
371
+ return Promise.resolve<any>({});
372
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
373
+ Unsafe return of a value of type \`Promise<any>\`.
374
+ }
375
+ `,
376
+ },
377
+ {
378
+ code: `
379
+ async function foo(): Promise<object> {
380
+ return Promise.resolve<Promise<Promise<any>>>({} as Promise<any>);
381
+ }
382
+ `,
383
+ snapshot: `
384
+ async function foo(): Promise<object> {
385
+ return Promise.resolve<Promise<Promise<any>>>({} as Promise<any>);
386
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
387
+ Unsafe return of a value of type \`Promise<any>\`.
388
+ }
389
+ `,
390
+ },
391
+ {
392
+ code: `
393
+ async function foo(): Promise<object> {
394
+ return {} as Promise<Promise<Promise<Promise<any>>>>;
395
+ }
396
+ `,
397
+ snapshot: `
398
+ async function foo(): Promise<object> {
399
+ return {} as Promise<Promise<Promise<Promise<any>>>>;
400
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
401
+ Unsafe return of a value of type \`Promise<any>\`.
402
+ }
403
+ `,
404
+ },
405
+ {
406
+ code: `
407
+ async function foo() {
408
+ return {} as Promise<Promise<Promise<Promise<any>>>>;
409
+ }
410
+ `,
411
+ snapshot: `
412
+ async function foo() {
413
+ return {} as Promise<Promise<Promise<Promise<any>>>>;
414
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
415
+ Unsafe return of a value of type \`Promise<any>\`.
416
+ }
417
+ `,
418
+ },
419
+ {
420
+ code: `
421
+ async function foo() {
422
+ return {} as Promise<any> | Promise<object>;
423
+ }
424
+ `,
425
+ snapshot: `
426
+ async function foo() {
427
+ return {} as Promise<any> | Promise<object>;
428
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
429
+ Unsafe return of a value of type \`Promise<any>\`.
430
+ }
431
+ `,
432
+ },
433
+ {
434
+ code: `
435
+ async function foo() {
436
+ return {} as Promise<any | object>;
437
+ }
438
+ `,
439
+ snapshot: `
440
+ async function foo() {
441
+ return {} as Promise<any | object>;
442
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
443
+ Unsafe return of a value of type \`Promise<any>\`.
444
+ }
445
+ `,
446
+ },
447
+ {
448
+ code: `
449
+ async function foo() {
450
+ return {} as Promise<any> & { __brand: 'any' };
451
+ }
452
+ `,
453
+ snapshot: `
454
+ async function foo() {
455
+ return {} as Promise<any> & { __brand: 'any' };
456
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
457
+ Unsafe return of a value of type \`Promise<any>\`.
458
+ }
459
+ `,
460
+ },
461
+ {
462
+ code: `
463
+ interface Alias<T> extends Promise<any> {
464
+ foo: 'bar';
465
+ }
466
+
467
+ declare const value: Alias<number>;
468
+ async function foo() {
469
+ return value;
470
+ }
471
+ `,
472
+ snapshot: `
473
+ interface Alias<T> extends Promise<any> {
474
+ foo: 'bar';
475
+ }
476
+
477
+ declare const value: Alias<number>;
478
+ async function foo() {
479
+ return value;
480
+ ~~~~~~~~~~~~~
481
+ Unsafe return of a value of type \`Promise<any>\`.
482
+ }
483
+ `,
484
+ },
485
+ ],
486
+ valid: [
487
+ `
488
+ return 1 as any;
489
+ `,
490
+ `
491
+ function foo() {
492
+ return;
493
+ }
494
+ `,
495
+ `
496
+ function foo() {
497
+ return 1;
498
+ }
499
+ `,
500
+ `
501
+ function foo() {
502
+ return '';
503
+ }
504
+ `,
505
+ `
506
+ function foo() {
507
+ return true;
508
+ }
509
+ `,
510
+ // this actually types as `never[]`
511
+ `
512
+ function foo() {
513
+ return [];
514
+ }
515
+ `,
516
+ // explicit any return type is allowed, if you want to be unsafe like that
517
+ `
518
+ function foo(): any {
519
+ return {} as any;
520
+ }
521
+ `,
522
+ `
523
+ declare function foo(arg: () => any): void;
524
+ foo((): any => 'foo' as any);
525
+ `,
526
+ `
527
+ declare function foo(arg: null | (() => any)): void;
528
+ foo((): any => 'foo' as any);
529
+ `,
530
+ // explicit any array return type is allowed, if you want to be unsafe like that
531
+ `
532
+ function foo(): any[] {
533
+ return [] as any[];
534
+ }
535
+ `,
536
+ // explicit any generic return type is allowed, if you want to be unsafe like that
537
+ `
538
+ function foo(): Set<any> {
539
+ return new Set<any>();
540
+ }
541
+ `,
542
+ `
543
+ async function foo(): Promise<any> {
544
+ return Promise.resolve({} as any);
545
+ }
546
+ `,
547
+ `
548
+ async function foo(): Promise<any> {
549
+ return {} as any;
550
+ }
551
+ `,
552
+ `
553
+ function foo(): object {
554
+ return Promise.resolve({} as any);
555
+ }
556
+ `,
557
+ // TODO - this should error, but it's hard to detect, as the type references are different
558
+ `
559
+ function foo(): ReadonlySet<number> {
560
+ return new Set<any>();
561
+ }
562
+ `,
563
+ `
564
+ function foo(): Set<number> {
565
+ return new Set([1]);
566
+ }
567
+ `,
568
+ `
569
+ type Foo<T = number> = { prop: T };
570
+ function foo(): Foo {
571
+ return { prop: 1 } as Foo<number>;
572
+ }
573
+ `,
574
+ `
575
+ type Foo = { prop: any };
576
+ function foo(): Foo {
577
+ return { prop: '' } as Foo;
578
+ }
579
+ `,
580
+ // TS 3.9 changed this to be safe
581
+ `
582
+ function fn<T extends any>(x: T) {
583
+ return x;
584
+ }
585
+ `,
586
+ `
587
+ function fn<T extends any>(x: T): unknown {
588
+ return x as any;
589
+ }
590
+ `,
591
+ `
592
+ function fn<T extends any>(x: T): unknown[] {
593
+ return x as any[];
594
+ }
595
+ `,
596
+ `
597
+ function fn<T extends any>(x: T): Set<unknown> {
598
+ return x as Set<any>;
599
+ }
600
+ `,
601
+ `
602
+ async function fn<T extends any>(x: T): Promise<unknown> {
603
+ return x as any;
604
+ }
605
+ `,
606
+ `
607
+ function fn<T extends any>(x: T): Promise<unknown> {
608
+ return Promise.resolve(x as any);
609
+ }
610
+ `,
611
+ // https://github.com/typescript-eslint/typescript-eslint/issues/2109
612
+ `
613
+ function test(): Map<string, string> {
614
+ return new Map();
615
+ }
616
+ `,
617
+ // https://github.com/typescript-eslint/typescript-eslint/issues/3549
618
+ `
619
+ function foo(): any {
620
+ return [] as any[];
621
+ }
622
+ `,
623
+ `
624
+ function foo(): unknown {
625
+ return [] as any[];
626
+ }
627
+ `,
628
+ `
629
+ declare const value: Promise<any>;
630
+ function foo() {
631
+ return value;
632
+ }
633
+ `,
634
+ "const foo: (() => void) | undefined = () => 1;",
635
+ `
636
+ class Foo {
637
+ public foo(): this {
638
+ return this;
639
+ }
640
+
641
+ protected then(resolve: () => void): void {
642
+ resolve();
643
+ }
644
+ }
645
+ `,
646
+ ],
647
+ });
@@ -0,0 +1,6 @@
1
+ declare const _default: import("@flint.fyi/core").Rule<{
2
+ readonly description: "Reports switch statements with duplicate case clause test expressions.";
3
+ readonly id: "caseDuplicates";
4
+ readonly preset: "logical";
5
+ }, import("../nodes.js").TSNodesByName, import("../language.js").TypeScriptServices, "duplicateCase", undefined>;
6
+ export default _default;
@@ -0,0 +1,49 @@
1
+ import * as ts from "typescript";
2
+ import { typescriptLanguage } from "../language.js";
3
+ import { hasSameTokens } from "../utils/hasSameTokens.js";
4
+ export default typescriptLanguage.createRule({
5
+ about: {
6
+ description: "Reports switch statements with duplicate case clause test expressions.",
7
+ id: "caseDuplicates",
8
+ preset: "logical",
9
+ },
10
+ messages: {
11
+ duplicateCase: {
12
+ primary: "This case duplicates a previous case, so it will never be reached.",
13
+ secondary: [
14
+ "Having duplicate case clauses in a switch statement is a logic error.",
15
+ "The second case clause will never be reached because the first matching case will always execute first.",
16
+ ],
17
+ suggestions: [
18
+ "Remove the duplicate case clause or modify its test expression to be unique.",
19
+ ],
20
+ },
21
+ },
22
+ setup(context) {
23
+ return {
24
+ visitors: {
25
+ SwitchStatement: (node) => {
26
+ const seenCases = [];
27
+ for (const clause of node.caseBlock.clauses) {
28
+ if (!ts.isCaseClause(clause)) {
29
+ continue;
30
+ }
31
+ const isDuplicate = seenCases.some((seenCase) => hasSameTokens(seenCase, clause.expression, context.sourceFile));
32
+ if (isDuplicate) {
33
+ context.report({
34
+ message: "duplicateCase",
35
+ range: {
36
+ begin: clause.getStart(context.sourceFile),
37
+ end: clause.expression.getEnd(),
38
+ },
39
+ });
40
+ }
41
+ else {
42
+ seenCases.push(clause.expression);
43
+ }
44
+ }
45
+ },
46
+ },
47
+ };
48
+ },
49
+ });
@@ -0,0 +1 @@
1
+ export {};