eslint-plugin-ts-data-forge 0.9.0 → 0.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.
- package/README.md +1 -0
- package/dist/plugin.d.mts +2 -0
- package/dist/plugin.d.mts.map +1 -1
- package/dist/plugin.mjs +1 -0
- package/dist/plugin.mjs.map +1 -1
- package/dist/rule-types.d.mts +15 -0
- package/dist/rule-types.d.mts.map +1 -1
- package/dist/rule-types.mjs.map +1 -1
- package/dist/rules/prefer-pipe-map-nullable.d.mts +24 -0
- package/dist/rules/prefer-pipe-map-nullable.d.mts.map +1 -0
- package/dist/rules/prefer-pipe-map-nullable.mjs +266 -0
- package/dist/rules/prefer-pipe-map-nullable.mjs.map +1 -0
- package/dist/rules/rules.d.mts +1 -0
- package/dist/rules/rules.d.mts.map +1 -1
- package/dist/rules/rules.mjs +2 -0
- package/dist/rules/rules.mjs.map +1 -1
- package/package.json +4 -4
- package/src/plugin.mts +1 -0
- package/src/rule-types.mts +16 -0
- package/src/rules/prefer-pipe-map-nullable.mts +391 -0
- package/src/rules/prefer-pipe-map-nullable.test.mts +470 -0
- package/src/rules/rules.mts +2 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
import parser from '@typescript-eslint/parser';
|
|
2
|
+
import { RuleTester } from '@typescript-eslint/rule-tester';
|
|
3
|
+
import dedent from 'dedent';
|
|
4
|
+
import { preferPipeMapNullable } from './prefer-pipe-map-nullable.mjs';
|
|
5
|
+
|
|
6
|
+
const tester = new RuleTester({
|
|
7
|
+
languageOptions: {
|
|
8
|
+
parser,
|
|
9
|
+
parserOptions: {
|
|
10
|
+
ecmaVersion: 2020,
|
|
11
|
+
sourceType: 'module',
|
|
12
|
+
projectService: {
|
|
13
|
+
allowDefaultProject: ['*.ts*'],
|
|
14
|
+
},
|
|
15
|
+
tsconfigRootDir: `${import.meta.dirname}/../..`,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
/** The same rule with no type information. */
|
|
21
|
+
const untypedTester = new RuleTester({
|
|
22
|
+
languageOptions: {
|
|
23
|
+
parser,
|
|
24
|
+
parserOptions: {
|
|
25
|
+
ecmaVersion: 2020,
|
|
26
|
+
sourceType: 'module',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('prefer-pipe-map-nullable', () => {
|
|
32
|
+
tester.run('prefer-pipe-map-nullable', preferPipeMapNullable, {
|
|
33
|
+
valid: [
|
|
34
|
+
{
|
|
35
|
+
name: 'ignores pipe(x).mapNullable(fn)',
|
|
36
|
+
code: dedent`
|
|
37
|
+
import { pipe } from 'ts-data-forge';
|
|
38
|
+
declare const x: number | undefined;
|
|
39
|
+
const y = pipe(x).mapNullable((v) => v + 1).value;
|
|
40
|
+
`,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'ignores map with another function',
|
|
44
|
+
code: dedent`
|
|
45
|
+
import { pipe } from 'ts-data-forge';
|
|
46
|
+
declare const x: number | undefined;
|
|
47
|
+
declare const f: (v: number | undefined) => number;
|
|
48
|
+
const y = pipe(x).map(f).value;
|
|
49
|
+
`,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'ignores the two-argument mapNullable(value, fn)',
|
|
53
|
+
code: dedent`
|
|
54
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
55
|
+
declare const x: number | undefined;
|
|
56
|
+
declare const g: (v: number | undefined) => (w: number) => number;
|
|
57
|
+
const y = pipe(x).map((v) => mapNullable(v, (w) => w + 1)).value;
|
|
58
|
+
const z = pipe(x).map(g(mapNullable(x, (w) => w + 1))).value;
|
|
59
|
+
`,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'ignores mapNullable with explicit type arguments',
|
|
63
|
+
code: dedent`
|
|
64
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
65
|
+
declare const x: number | undefined;
|
|
66
|
+
const y = pipe(x).map(mapNullable<number, number>((v) => v + 1)).value;
|
|
67
|
+
`,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'ignores map with explicit type arguments',
|
|
71
|
+
code: dedent`
|
|
72
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
73
|
+
declare const x: number | undefined;
|
|
74
|
+
const y = pipe(x).map<number | undefined>(mapNullable((v: number) => v + 1)).value;
|
|
75
|
+
`,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'ignores a mapNullable not imported from ts-data-forge',
|
|
79
|
+
code: dedent`
|
|
80
|
+
import { pipe } from 'ts-data-forge';
|
|
81
|
+
const mapNullable =
|
|
82
|
+
<A, B>(fn: (a: A) => B) =>
|
|
83
|
+
(a: A | null | undefined): B | undefined =>
|
|
84
|
+
a == null ? undefined : fn(a);
|
|
85
|
+
declare const x: number | undefined;
|
|
86
|
+
const y = pipe(x).map(mapNullable((v: number) => v + 1)).value;
|
|
87
|
+
`,
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: 'ignores a mapNullable that shadows the import',
|
|
91
|
+
code: dedent`
|
|
92
|
+
import { mapNullable as _m, pipe } from 'ts-data-forge';
|
|
93
|
+
import { mapNullable } from 'ts-data-forge';
|
|
94
|
+
declare const x: number | undefined;
|
|
95
|
+
const run = (mapNullable: (fn: (v: number) => number) => (v: number | undefined) => number) =>
|
|
96
|
+
pipe(x).map(mapNullable((v) => v + 1)).value;
|
|
97
|
+
`,
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'ignores a map on something that is not a pipe',
|
|
101
|
+
code: dedent`
|
|
102
|
+
import { mapNullable } from 'ts-data-forge';
|
|
103
|
+
declare const xs: readonly (number | undefined)[];
|
|
104
|
+
const ys = xs.map(mapNullable((v) => v + 1));
|
|
105
|
+
`,
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: 'ignores a pipe not imported from ts-data-forge',
|
|
109
|
+
code: dedent`
|
|
110
|
+
import { mapNullable } from 'ts-data-forge';
|
|
111
|
+
import { pipe } from 'some-other-pipe';
|
|
112
|
+
declare const x: number | undefined;
|
|
113
|
+
const y = pipe(x).map(mapNullable((v: number) => v + 1));
|
|
114
|
+
`,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: 'ignores a pipe held in a variable',
|
|
118
|
+
code: dedent`
|
|
119
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
120
|
+
declare const x: number | undefined;
|
|
121
|
+
const p = pipe(x);
|
|
122
|
+
const y = p.map(mapNullable((v) => v + 1)).value;
|
|
123
|
+
`,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: 'ignores optional calls',
|
|
127
|
+
code: dedent`
|
|
128
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
129
|
+
declare const x: number | undefined;
|
|
130
|
+
const y = pipe(x).map?.(mapNullable((v) => v + 1));
|
|
131
|
+
`,
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: 'ignores a spread argument',
|
|
135
|
+
code: dedent`
|
|
136
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
137
|
+
declare const x: number | undefined;
|
|
138
|
+
declare const args: readonly [(v: number) => number];
|
|
139
|
+
const y = pipe(x).map(mapNullable(...args));
|
|
140
|
+
`,
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
invalid: [
|
|
144
|
+
{
|
|
145
|
+
name: 'fixes an inline function whose result type is not a literal',
|
|
146
|
+
code: dedent`
|
|
147
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
148
|
+
declare const x: number | undefined;
|
|
149
|
+
const y = pipe(x).map(mapNullable((v) => v + 1)).value;
|
|
150
|
+
`,
|
|
151
|
+
output: dedent`
|
|
152
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
153
|
+
declare const x: number | undefined;
|
|
154
|
+
const y = pipe(x).mapNullable((v) => v + 1).value;
|
|
155
|
+
`,
|
|
156
|
+
errors: [{ messageId: 'useMapNullable' }],
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: 'fixes a function reference',
|
|
160
|
+
code: dedent`
|
|
161
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
162
|
+
declare const x: string | undefined;
|
|
163
|
+
declare const f: (s: string) => 'a';
|
|
164
|
+
const y = pipe(x).map(mapNullable(f)).value;
|
|
165
|
+
`,
|
|
166
|
+
output: dedent`
|
|
167
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
168
|
+
declare const x: string | undefined;
|
|
169
|
+
declare const f: (s: string) => 'a';
|
|
170
|
+
const y = pipe(x).mapNullable(f).value;
|
|
171
|
+
`,
|
|
172
|
+
errors: [{ messageId: 'useMapNullable' }],
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: 'fixes an inline function with a return type annotation',
|
|
176
|
+
code: dedent`
|
|
177
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
178
|
+
declare const x: number | undefined;
|
|
179
|
+
const y = pipe(x).map(mapNullable((v): 'a' => 'a')).value;
|
|
180
|
+
`,
|
|
181
|
+
output: dedent`
|
|
182
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
183
|
+
declare const x: number | undefined;
|
|
184
|
+
const y = pipe(x).mapNullable((v): 'a' => 'a').value;
|
|
185
|
+
`,
|
|
186
|
+
errors: [{ messageId: 'useMapNullable' }],
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
name: 'fixes an inline function returning an object of non-literals',
|
|
190
|
+
code: dedent`
|
|
191
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
192
|
+
declare const x: number | undefined;
|
|
193
|
+
const y = pipe(x).map(mapNullable((v) => ({ v, ok: v > 0 }))).value;
|
|
194
|
+
`,
|
|
195
|
+
output: dedent`
|
|
196
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
197
|
+
declare const x: number | undefined;
|
|
198
|
+
const y = pipe(x).mapNullable((v) => ({ v, ok: v > 0 })).value;
|
|
199
|
+
`,
|
|
200
|
+
errors: [{ messageId: 'useMapNullable' }],
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: 'fixes every link of a chain',
|
|
204
|
+
code: dedent`
|
|
205
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
206
|
+
declare const x: string | undefined;
|
|
207
|
+
const y = pipe(x)
|
|
208
|
+
.map(mapNullable((s) => s.length))
|
|
209
|
+
.map((n) => n)
|
|
210
|
+
.map(mapNullable((n) => n * 2)).value;
|
|
211
|
+
`,
|
|
212
|
+
output: dedent`
|
|
213
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
214
|
+
declare const x: string | undefined;
|
|
215
|
+
const y = pipe(x)
|
|
216
|
+
.mapNullable((s) => s.length)
|
|
217
|
+
.map((n) => n)
|
|
218
|
+
.mapNullable((n) => n * 2).value;
|
|
219
|
+
`,
|
|
220
|
+
errors: [
|
|
221
|
+
{ messageId: 'useMapNullable' },
|
|
222
|
+
{ messageId: 'useMapNullable' },
|
|
223
|
+
],
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
name: 'fixes after mapOptional and mapNullable links',
|
|
227
|
+
code: dedent`
|
|
228
|
+
import { mapNullable, Optional, pipe } from 'ts-data-forge';
|
|
229
|
+
declare const o: Optional<number>;
|
|
230
|
+
const y = pipe(o)
|
|
231
|
+
.mapOptional((n) => n + 1)
|
|
232
|
+
.map((p) => Optional.unwrapOr(p, undefined))
|
|
233
|
+
.mapNullable((n) => n)
|
|
234
|
+
.map(mapNullable((n) => n * 2)).value;
|
|
235
|
+
`,
|
|
236
|
+
output: dedent`
|
|
237
|
+
import { mapNullable, Optional, pipe } from 'ts-data-forge';
|
|
238
|
+
declare const o: Optional<number>;
|
|
239
|
+
const y = pipe(o)
|
|
240
|
+
.mapOptional((n) => n + 1)
|
|
241
|
+
.map((p) => Optional.unwrapOr(p, undefined))
|
|
242
|
+
.mapNullable((n) => n)
|
|
243
|
+
.mapNullable((n) => n * 2).value;
|
|
244
|
+
`,
|
|
245
|
+
errors: [{ messageId: 'useMapNullable' }],
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
name: 'fixes aliased and namespace imports',
|
|
249
|
+
code: dedent`
|
|
250
|
+
import * as tdf from 'ts-data-forge';
|
|
251
|
+
import { mapNullable as mapN } from 'ts-data-forge';
|
|
252
|
+
declare const x: number | undefined;
|
|
253
|
+
const y = tdf.pipe(x).map(tdf.mapNullable((v) => v + 1)).value;
|
|
254
|
+
const z = tdf.pipe(x).map(mapN((v) => v + 1)).value;
|
|
255
|
+
`,
|
|
256
|
+
output: dedent`
|
|
257
|
+
import * as tdf from 'ts-data-forge';
|
|
258
|
+
import { mapNullable as mapN } from 'ts-data-forge';
|
|
259
|
+
declare const x: number | undefined;
|
|
260
|
+
const y = tdf.pipe(x).mapNullable((v) => v + 1).value;
|
|
261
|
+
const z = tdf.pipe(x).mapNullable((v) => v + 1).value;
|
|
262
|
+
`,
|
|
263
|
+
errors: [
|
|
264
|
+
{ messageId: 'useMapNullable' },
|
|
265
|
+
{ messageId: 'useMapNullable' },
|
|
266
|
+
],
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
name: 'fixes a pipe imported from ts-std-forge',
|
|
270
|
+
code: dedent`
|
|
271
|
+
import { mapNullable } from 'ts-data-forge';
|
|
272
|
+
import { pipe } from 'ts-std-forge';
|
|
273
|
+
declare const x: number | undefined;
|
|
274
|
+
const y = pipe(x).map(mapNullable((v) => v + 1)).value;
|
|
275
|
+
`,
|
|
276
|
+
output: dedent`
|
|
277
|
+
import { mapNullable } from 'ts-data-forge';
|
|
278
|
+
import { pipe } from 'ts-std-forge';
|
|
279
|
+
declare const x: number | undefined;
|
|
280
|
+
const y = pipe(x).mapNullable((v) => v + 1).value;
|
|
281
|
+
`,
|
|
282
|
+
errors: [{ messageId: 'useMapNullable' }],
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
name: 'keeps comments around the function and a sequence argument',
|
|
286
|
+
code: dedent`
|
|
287
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
288
|
+
declare const x: number | undefined;
|
|
289
|
+
declare const f: (v: number) => number;
|
|
290
|
+
const y = pipe(x).map(/* a */ mapNullable((0, f)) /* b */).value;
|
|
291
|
+
`,
|
|
292
|
+
output: dedent`
|
|
293
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
294
|
+
declare const x: number | undefined;
|
|
295
|
+
declare const f: (v: number) => number;
|
|
296
|
+
const y = pipe(x).mapNullable(/* a */ (0, f) /* b */).value;
|
|
297
|
+
`,
|
|
298
|
+
errors: [{ messageId: 'useMapNullable' }],
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
name: 'suggests when the inferred result is a literal',
|
|
302
|
+
code: dedent`
|
|
303
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
304
|
+
declare const x: number | undefined;
|
|
305
|
+
const y = pipe(x).map(mapNullable((v) => 'a')).value;
|
|
306
|
+
`,
|
|
307
|
+
errors: [
|
|
308
|
+
{
|
|
309
|
+
messageId: 'useMapNullable',
|
|
310
|
+
suggestions: [
|
|
311
|
+
{
|
|
312
|
+
messageId: 'suggestMapNullable',
|
|
313
|
+
output: dedent`
|
|
314
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
315
|
+
declare const x: number | undefined;
|
|
316
|
+
const y = pipe(x).mapNullable((v) => 'a').value;
|
|
317
|
+
`,
|
|
318
|
+
},
|
|
319
|
+
],
|
|
320
|
+
},
|
|
321
|
+
],
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
name: 'suggests when the inferred result is a tuple',
|
|
325
|
+
code: dedent`
|
|
326
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
327
|
+
declare const x: number | undefined;
|
|
328
|
+
const y = pipe(x).map(mapNullable((v) => [v, 1])).value;
|
|
329
|
+
`,
|
|
330
|
+
errors: [
|
|
331
|
+
{
|
|
332
|
+
messageId: 'useMapNullable',
|
|
333
|
+
suggestions: [
|
|
334
|
+
{
|
|
335
|
+
messageId: 'suggestMapNullable',
|
|
336
|
+
output: dedent`
|
|
337
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
338
|
+
declare const x: number | undefined;
|
|
339
|
+
const y = pipe(x).mapNullable((v) => [v, 1]).value;
|
|
340
|
+
`,
|
|
341
|
+
},
|
|
342
|
+
],
|
|
343
|
+
},
|
|
344
|
+
],
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
name: 'suggests when a literal is nested in an object',
|
|
348
|
+
code: dedent`
|
|
349
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
350
|
+
declare const x: number | undefined;
|
|
351
|
+
const y = pipe(x).map(mapNullable((v) => ({ kind: 'n', v }))).value;
|
|
352
|
+
`,
|
|
353
|
+
errors: [
|
|
354
|
+
{
|
|
355
|
+
messageId: 'useMapNullable',
|
|
356
|
+
suggestions: [
|
|
357
|
+
{
|
|
358
|
+
messageId: 'suggestMapNullable',
|
|
359
|
+
output: dedent`
|
|
360
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
361
|
+
declare const x: number | undefined;
|
|
362
|
+
const y = pipe(x).mapNullable((v) => ({ kind: 'n', v })).value;
|
|
363
|
+
`,
|
|
364
|
+
},
|
|
365
|
+
],
|
|
366
|
+
},
|
|
367
|
+
],
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
name: 'suggests when a comment inside mapNullable(…) would be dropped',
|
|
371
|
+
code: dedent`
|
|
372
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
373
|
+
declare const x: number | undefined;
|
|
374
|
+
declare const f: (v: number) => number;
|
|
375
|
+
const y = pipe(x).map(mapNullable(/* keep */ f)).value;
|
|
376
|
+
`,
|
|
377
|
+
errors: [
|
|
378
|
+
{
|
|
379
|
+
messageId: 'useMapNullable',
|
|
380
|
+
suggestions: [
|
|
381
|
+
{
|
|
382
|
+
messageId: 'suggestMapNullable',
|
|
383
|
+
output: dedent`
|
|
384
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
385
|
+
declare const x: number | undefined;
|
|
386
|
+
declare const f: (v: number) => number;
|
|
387
|
+
const y = pipe(x).mapNullable(f).value;
|
|
388
|
+
`,
|
|
389
|
+
},
|
|
390
|
+
],
|
|
391
|
+
},
|
|
392
|
+
],
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
name: 'suggests when a type wrapper around mapNullable would be dropped',
|
|
396
|
+
code: dedent`
|
|
397
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
398
|
+
declare const x: number | undefined;
|
|
399
|
+
declare const f: (v: number) => number;
|
|
400
|
+
const y = pipe(x).map((mapNullable as typeof mapNullable)(f)).value;
|
|
401
|
+
`,
|
|
402
|
+
errors: [
|
|
403
|
+
{
|
|
404
|
+
messageId: 'useMapNullable',
|
|
405
|
+
suggestions: [
|
|
406
|
+
{
|
|
407
|
+
messageId: 'suggestMapNullable',
|
|
408
|
+
output: dedent`
|
|
409
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
410
|
+
declare const x: number | undefined;
|
|
411
|
+
declare const f: (v: number) => number;
|
|
412
|
+
const y = pipe(x).mapNullable(f).value;
|
|
413
|
+
`,
|
|
414
|
+
},
|
|
415
|
+
],
|
|
416
|
+
},
|
|
417
|
+
],
|
|
418
|
+
},
|
|
419
|
+
],
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
untypedTester.run(
|
|
423
|
+
'prefer-pipe-map-nullable (no type information)',
|
|
424
|
+
preferPipeMapNullable,
|
|
425
|
+
{
|
|
426
|
+
valid: [],
|
|
427
|
+
invalid: [
|
|
428
|
+
{
|
|
429
|
+
name: 'fixes a function reference',
|
|
430
|
+
code: dedent`
|
|
431
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
432
|
+
declare const x: number | undefined;
|
|
433
|
+
declare const f: (v: number) => number;
|
|
434
|
+
const y = pipe(x).map(mapNullable(f)).value;
|
|
435
|
+
`,
|
|
436
|
+
output: dedent`
|
|
437
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
438
|
+
declare const x: number | undefined;
|
|
439
|
+
declare const f: (v: number) => number;
|
|
440
|
+
const y = pipe(x).mapNullable(f).value;
|
|
441
|
+
`,
|
|
442
|
+
errors: [{ messageId: 'useMapNullable' }],
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
name: 'suggests for an inline function it cannot type',
|
|
446
|
+
code: dedent`
|
|
447
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
448
|
+
declare const x: number | undefined;
|
|
449
|
+
const y = pipe(x).map(mapNullable((v) => v + 1)).value;
|
|
450
|
+
`,
|
|
451
|
+
errors: [
|
|
452
|
+
{
|
|
453
|
+
messageId: 'useMapNullable',
|
|
454
|
+
suggestions: [
|
|
455
|
+
{
|
|
456
|
+
messageId: 'suggestMapNullable',
|
|
457
|
+
output: dedent`
|
|
458
|
+
import { mapNullable, pipe } from 'ts-data-forge';
|
|
459
|
+
declare const x: number | undefined;
|
|
460
|
+
const y = pipe(x).mapNullable((v) => v + 1).value;
|
|
461
|
+
`,
|
|
462
|
+
},
|
|
463
|
+
],
|
|
464
|
+
},
|
|
465
|
+
],
|
|
466
|
+
},
|
|
467
|
+
],
|
|
468
|
+
},
|
|
469
|
+
);
|
|
470
|
+
});
|
package/src/rules/rules.mts
CHANGED
|
@@ -16,6 +16,7 @@ import { preferIsRecordAndHasKey } from './prefer-is-record-and-has-key.mjs';
|
|
|
16
16
|
import { preferNumSafeParseFloat } from './prefer-num-safe-parse-float.mjs';
|
|
17
17
|
import { preferNumSafeParseInt } from './prefer-num-safe-parse-int.mjs';
|
|
18
18
|
import { preferObjOverEntriesRoundTrip } from './prefer-obj-over-entries-round-trip.mjs';
|
|
19
|
+
import { preferPipeMapNullable } from './prefer-pipe-map-nullable.mjs';
|
|
19
20
|
import { preferRangeForLoop } from './prefer-range-for-loop.mjs';
|
|
20
21
|
|
|
21
22
|
export const tsDataForgeRules = {
|
|
@@ -37,4 +38,5 @@ export const tsDataForgeRules = {
|
|
|
37
38
|
'no-unnecessary-type-guard': noUnnecessaryTypeGuard,
|
|
38
39
|
'prefer-comparison-over-nullish-guard': preferComparisonOverNullishGuard,
|
|
39
40
|
'prefer-obj-over-entries-round-trip': preferObjOverEntriesRoundTrip,
|
|
41
|
+
'prefer-pipe-map-nullable': preferPipeMapNullable,
|
|
40
42
|
} as const satisfies ESLintPlugin['rules'];
|