eslint-plugin-ts-data-forge 0.10.4 → 0.10.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-ts-data-forge",
3
- "version": "0.10.4",
3
+ "version": "0.10.5",
4
4
  "private": false,
5
5
  "description": "ESLint rules that steer code toward ts-data-forge idioms.",
6
6
  "keywords": [
@@ -35,7 +35,7 @@
35
35
  ],
36
36
  "dependencies": {
37
37
  "@typescript-eslint/utils": "^8.72.0",
38
- "eslint-rule-forge": "^0.3.2",
38
+ "eslint-rule-forge": "^0.4.0",
39
39
  "ts-data-forge": "14.10.0",
40
40
  "ts-type-forge": "~9.2.2"
41
41
  },
@@ -43,9 +43,9 @@
43
43
  "@typescript-eslint/parser": "8.72.0",
44
44
  "@typescript-eslint/rule-tester": "8.72.0",
45
45
  "dedent": "1.7.2",
46
- "eslint-config-typed": "5.20.1",
47
- "eslint-plugin-ts-fortress": "1.3.9",
48
- "eslint-plugin-ts-type-forge": "0.8.14",
46
+ "eslint-config-typed": "7.1.0",
47
+ "eslint-plugin-ts-fortress": "1.3.10",
48
+ "eslint-plugin-ts-type-forge": "0.8.15",
49
49
  "prettier": "3.9.10",
50
50
  "prettier-plugin-organize-imports": "4.3.0",
51
51
  "prettier-plugin-packagejson": "3.0.2",
@@ -72,11 +72,18 @@ ruleTester.run('prefer-arr-is-array', preferArrIsArray, {
72
72
  const result1 = Array.isArray(value1);
73
73
  const result2 = Array.isArray(value2);
74
74
  `,
75
- output: dedent`
76
- import { Arr } from 'ts-data-forge';
77
- const result1 = Arr.isArray(value1);
78
- const result2 = Arr.isArray(value2);
79
- `,
75
+ output: [
76
+ dedent`
77
+ import { Arr } from 'ts-data-forge';
78
+ const result1 = Arr.isArray(value1);
79
+ const result2 = Array.isArray(value2);
80
+ `,
81
+ dedent`
82
+ import { Arr } from 'ts-data-forge';
83
+ const result1 = Arr.isArray(value1);
84
+ const result2 = Arr.isArray(value2);
85
+ `,
86
+ ],
80
87
  errors: [{ messageId: 'useIsArray' }, { messageId: 'useIsArray' }],
81
88
  },
82
89
  ],
@@ -157,3 +164,78 @@ describe('prefer-arr-is-array with parenthesized operands', () => {
157
164
  ],
158
165
  });
159
166
  });
167
+
168
+ describe('prefer-arr-is-array brings Arr into scope', () => {
169
+ ruleTester.run('prefer-arr-is-array', preferArrIsArray, {
170
+ valid: [],
171
+ invalid: [
172
+ {
173
+ name: 'after a leading directive',
174
+ code: dedent`
175
+ 'use client';
176
+ const result = Array.isArray(value);
177
+ `,
178
+ output: dedent`
179
+ 'use client';
180
+ import { Arr } from 'ts-data-forge';
181
+ const result = Arr.isArray(value);
182
+ `,
183
+ errors: [{ messageId: 'useIsArray' }],
184
+ },
185
+ {
186
+ name: 'in the existing named import',
187
+ code: dedent`
188
+ import { Num } from 'ts-data-forge';
189
+ const result = Array.isArray(value);
190
+ `,
191
+ output: dedent`
192
+ import { Num, Arr } from 'ts-data-forge';
193
+ const result = Arr.isArray(value);
194
+ `,
195
+ errors: [{ messageId: 'useIsArray' }],
196
+ },
197
+ {
198
+ name: 'an inline type import becomes a value import',
199
+ code: dedent`
200
+ import { type Arr } from 'ts-data-forge';
201
+ const result = Array.isArray(value);
202
+ `,
203
+ output: dedent`
204
+ import { Arr } from 'ts-data-forge';
205
+ const result = Arr.isArray(value);
206
+ `,
207
+ errors: [{ messageId: 'useIsArray' }],
208
+ },
209
+ {
210
+ name: 'no fix when a type-only declaration imports it',
211
+ code: dedent`
212
+ import type { Arr } from 'ts-data-forge';
213
+ const result = Array.isArray(value);
214
+ `,
215
+ output: null,
216
+ errors: [{ messageId: 'useIsArray' }],
217
+ },
218
+ {
219
+ name: 'the local name of an aliased import',
220
+ code: dedent`
221
+ import { Arr as A } from 'ts-data-forge';
222
+ const result = Array.isArray(value);
223
+ `,
224
+ output: dedent`
225
+ import { Arr as A } from 'ts-data-forge';
226
+ const result = A.isArray(value);
227
+ `,
228
+ errors: [{ messageId: 'useIsArray' }],
229
+ },
230
+ {
231
+ name: 'no fix when something else is named Arr where the call is',
232
+ code: dedent`
233
+ const Arr = 1;
234
+ const result = Array.isArray(value);
235
+ `,
236
+ output: null,
237
+ errors: [{ messageId: 'useIsArray' }],
238
+ },
239
+ ],
240
+ });
241
+ });
@@ -60,24 +60,6 @@ describe('prefer-is-non-null-object', () => {
60
60
  `,
61
61
  errors: [{ messageId: 'useIsNonNullObject' }],
62
62
  },
63
- {
64
- name: 'replaces multiple typeof object checks with isNonNullObject imports',
65
- code: dedent`
66
- const u = {};
67
- const ok = typeof u === "object" && u !== null;
68
- const ok2 = typeof u === "object" && u !== null;
69
- `,
70
- output: dedent`
71
- import { isNonNullObject } from 'ts-data-forge';
72
- const u = {};
73
- const ok = isNonNullObject(u);
74
- const ok2 = isNonNullObject(u);
75
- `,
76
- errors: [
77
- { messageId: 'useIsNonNullObject' },
78
- { messageId: 'useIsNonNullObject' },
79
- ],
80
- },
81
63
  ] as const),
82
64
 
83
65
  ...([
@@ -124,8 +106,7 @@ describe('prefer-is-non-null-object', () => {
124
106
  const ok = typeof u === "object" && u !== null;
125
107
  `,
126
108
  output: dedent`
127
- import { isNonNullObject } from 'ts-data-forge';
128
- import { asInt } from 'ts-data-forge';
109
+ import { asInt, isNonNullObject } from 'ts-data-forge';
129
110
 
130
111
  const ok = isNonNullObject(u);
131
112
  `,
@@ -141,9 +122,8 @@ describe('prefer-is-non-null-object', () => {
141
122
  noop(typeof u === "object" && u !== null);
142
123
  `,
143
124
  output: dedent`
144
- import { isNonNullObject } from 'ts-data-forge';
145
125
  import { noop } from './noop.mjs';
146
- import { asInt } from 'ts-data-forge';
126
+ import { asInt, isNonNullObject } from 'ts-data-forge';
147
127
 
148
128
  const u = {};
149
129
  noop(isNonNullObject(u));
@@ -151,6 +131,32 @@ describe('prefer-is-non-null-object', () => {
151
131
  errors: [{ messageId: 'useIsNonNullObject' }],
152
132
  },
153
133
  ] as const),
134
+ {
135
+ name: 'replaces multiple typeof object checks with isNonNullObject imports',
136
+ code: dedent`
137
+ const u = {};
138
+ const ok = typeof u === "object" && u !== null;
139
+ const ok2 = typeof u === "object" && u !== null;
140
+ `,
141
+ output: [
142
+ dedent`
143
+ import { isNonNullObject } from 'ts-data-forge';
144
+ const u = {};
145
+ const ok = isNonNullObject(u);
146
+ const ok2 = typeof u === "object" && u !== null;
147
+ `,
148
+ dedent`
149
+ import { isNonNullObject } from 'ts-data-forge';
150
+ const u = {};
151
+ const ok = isNonNullObject(u);
152
+ const ok2 = isNonNullObject(u);
153
+ `,
154
+ ],
155
+ errors: [
156
+ { messageId: 'useIsNonNullObject' },
157
+ { messageId: 'useIsNonNullObject' },
158
+ ],
159
+ },
154
160
  ],
155
161
  });
156
162
  }, 20000);
@@ -298,15 +304,26 @@ describe('prefer-is-non-null-object in other forms', () => {
298
304
  const y = a && typeof u === 'object' && u !== null;
299
305
  const z = a && u !== null && (typeof u === 'object') && b;
300
306
  `,
301
- output: dedent`
302
- import { isNonNullObject } from 'ts-data-forge';
303
- declare const u: unknown;
304
- declare const a: boolean;
305
- declare const b: boolean;
306
- const x = isNonNullObject(u) && 'k' in u;
307
- const y = a && isNonNullObject(u);
308
- const z = a && isNonNullObject(u) && b;
309
- `,
307
+ output: [
308
+ dedent`
309
+ import { isNonNullObject } from 'ts-data-forge';
310
+ declare const u: unknown;
311
+ declare const a: boolean;
312
+ declare const b: boolean;
313
+ const x = isNonNullObject(u) && 'k' in u;
314
+ const y = a && typeof u === 'object' && u !== null;
315
+ const z = a && u !== null && (typeof u === 'object') && b;
316
+ `,
317
+ dedent`
318
+ import { isNonNullObject } from 'ts-data-forge';
319
+ declare const u: unknown;
320
+ declare const a: boolean;
321
+ declare const b: boolean;
322
+ const x = isNonNullObject(u) && 'k' in u;
323
+ const y = a && isNonNullObject(u);
324
+ const z = a && isNonNullObject(u) && b;
325
+ `,
326
+ ],
310
327
  errors: [
311
328
  { messageId: 'useIsNonNullObject' },
312
329
  { messageId: 'useIsNonNullObject' },
@@ -320,12 +337,20 @@ describe('prefer-is-non-null-object in other forms', () => {
320
337
  declare const v: unknown;
321
338
  const ok = typeof u === 'object' && u !== null && v !== null && typeof v === 'object';
322
339
  `,
323
- output: dedent`
324
- import { isNonNullObject } from 'ts-data-forge';
325
- declare const u: unknown;
326
- declare const v: unknown;
327
- const ok = isNonNullObject(u) && isNonNullObject(v);
328
- `,
340
+ output: [
341
+ dedent`
342
+ import { isNonNullObject } from 'ts-data-forge';
343
+ declare const u: unknown;
344
+ declare const v: unknown;
345
+ const ok = isNonNullObject(u) && v !== null && typeof v === 'object';
346
+ `,
347
+ dedent`
348
+ import { isNonNullObject } from 'ts-data-forge';
349
+ declare const u: unknown;
350
+ declare const v: unknown;
351
+ const ok = isNonNullObject(u) && isNonNullObject(v);
352
+ `,
353
+ ],
329
354
  errors: [
330
355
  { messageId: 'useIsNonNullObject' },
331
356
  { messageId: 'useIsNonNullObject' },
@@ -85,13 +85,22 @@ describe('prefer-is-record-and-has-key', () => {
85
85
  const a = Object.hasOwn(rec, 'a');
86
86
  const b = Object.hasOwn(unk, 'b');
87
87
  `,
88
- output: dedent`
89
- import { isRecord, hasKey } from 'ts-data-forge';
90
- declare const rec: Record<string, unknown>;
91
- declare const unk: unknown;
92
- const a = hasKey(rec, 'a');
93
- const b = (isRecord(unk) && hasKey(unk, 'b'));
94
- `,
88
+ output: [
89
+ dedent`
90
+ import { hasKey } from 'ts-data-forge';
91
+ declare const rec: Record<string, unknown>;
92
+ declare const unk: unknown;
93
+ const a = hasKey(rec, 'a');
94
+ const b = Object.hasOwn(unk, 'b');
95
+ `,
96
+ dedent`
97
+ import { hasKey, isRecord } from 'ts-data-forge';
98
+ declare const rec: Record<string, unknown>;
99
+ declare const unk: unknown;
100
+ const a = hasKey(rec, 'a');
101
+ const b = (isRecord(unk) && hasKey(unk, 'b'));
102
+ `,
103
+ ],
95
104
  errors: [
96
105
  { messageId: 'useHasKey' },
97
106
  { messageId: 'useIsRecordAndHasKey' },
@@ -162,8 +171,7 @@ describe('prefer-is-record-and-has-key', () => {
162
171
  const ok = Object.hasOwn(obj, 'a');
163
172
  `,
164
173
  output: dedent`
165
- import { hasKey } from 'ts-data-forge';
166
- import { isRecord } from 'ts-data-forge';
174
+ import { isRecord, hasKey } from 'ts-data-forge';
167
175
 
168
176
  const obj = { a: 1 };
169
177
  const ok = (isRecord(obj) && hasKey(obj, 'a'));
@@ -179,8 +187,7 @@ describe('prefer-is-record-and-has-key', () => {
179
187
  const ok = 'a' in obj;
180
188
  `,
181
189
  output: dedent`
182
- import { isRecord } from 'ts-data-forge';
183
- import { hasKey } from 'ts-data-forge';
190
+ import { hasKey, isRecord } from 'ts-data-forge';
184
191
 
185
192
  const obj = { a: 1 };
186
193
  const ok = (isRecord(obj) && hasKey(obj, 'a'));
@@ -210,12 +217,20 @@ describe('prefer-is-record-and-has-key', () => {
210
217
  const ok1 = Object.hasOwn(obj, 'a');
211
218
  const ok2 = 'b' in obj;
212
219
  `,
213
- output: dedent`
214
- import { isRecord, hasKey } from 'ts-data-forge';
215
- const obj = { a: 1 };
216
- const ok1 = (isRecord(obj) && hasKey(obj, 'a'));
217
- const ok2 = (isRecord(obj) && hasKey(obj, 'b'));
218
- `,
220
+ output: [
221
+ dedent`
222
+ import { isRecord, hasKey } from 'ts-data-forge';
223
+ const obj = { a: 1 };
224
+ const ok1 = (isRecord(obj) && hasKey(obj, 'a'));
225
+ const ok2 = 'b' in obj;
226
+ `,
227
+ dedent`
228
+ import { isRecord, hasKey } from 'ts-data-forge';
229
+ const obj = { a: 1 };
230
+ const ok1 = (isRecord(obj) && hasKey(obj, 'a'));
231
+ const ok2 = (isRecord(obj) && hasKey(obj, 'b'));
232
+ `,
233
+ ],
219
234
  errors: [
220
235
  { messageId: 'useIsRecordAndHasKey' },
221
236
  { messageId: 'useIsRecordAndHasKey' },
@@ -105,8 +105,7 @@ describe('prefer-num-safe-parse-float', () => {
105
105
  const n = parseFloat(s);
106
106
  `,
107
107
  output: dedent`
108
- import { Result } from 'ts-data-forge';
109
- import { Num } from 'ts-data-forge';
108
+ import { Num, Result } from 'ts-data-forge';
110
109
 
111
110
  const s = "3.14";
112
111
  const n = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
@@ -145,13 +144,22 @@ describe('prefer-num-safe-parse-float', () => {
145
144
  const b = Number.parseFloat(s);
146
145
  const c = Number(s);
147
146
  `,
148
- output: dedent`
149
- import { Num, Result } from 'ts-data-forge';
150
- const s = "1.5";
151
- const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
152
- const b = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
153
- const c = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
154
- `,
147
+ output: [
148
+ dedent`
149
+ import { Num, Result } from 'ts-data-forge';
150
+ const s = "1.5";
151
+ const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
152
+ const b = Number.parseFloat(s);
153
+ const c = Number(s);
154
+ `,
155
+ dedent`
156
+ import { Num, Result } from 'ts-data-forge';
157
+ const s = "1.5";
158
+ const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
159
+ const b = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
160
+ const c = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
161
+ `,
162
+ ],
155
163
  errors: [
156
164
  { messageId: 'useSafeParseFloat' },
157
165
  { messageId: 'useSafeParseFloat' },
@@ -203,12 +211,20 @@ describe('prefer-num-safe-parse-float through type wrappers', () => {
203
211
  const a = Number(s!);
204
212
  const b = parseFloat(s satisfies string);
205
213
  `,
206
- output: dedent`
207
- import { Num, Result } from 'ts-data-forge';
208
- declare const s: string;
209
- const a = Result.unwrapOkOr(Num.safeParseFloat(s!), Number.NaN);
210
- const b = Result.unwrapOkOr(Num.safeParseFloat(s satisfies string), Number.NaN);
211
- `,
214
+ output: [
215
+ dedent`
216
+ import { Num, Result } from 'ts-data-forge';
217
+ declare const s: string;
218
+ const a = Result.unwrapOkOr(Num.safeParseFloat(s!), Number.NaN);
219
+ const b = parseFloat(s satisfies string);
220
+ `,
221
+ dedent`
222
+ import { Num, Result } from 'ts-data-forge';
223
+ declare const s: string;
224
+ const a = Result.unwrapOkOr(Num.safeParseFloat(s!), Number.NaN);
225
+ const b = Result.unwrapOkOr(Num.safeParseFloat(s satisfies string), Number.NaN);
226
+ `,
227
+ ],
212
228
  errors: [
213
229
  { messageId: 'useSafeParseFloat' },
214
230
  { messageId: 'useSafeParseFloat' },
@@ -221,12 +237,20 @@ describe('prefer-num-safe-parse-float through type wrappers', () => {
221
237
  const a = (Number as NumberConstructor)(s);
222
238
  const b = Number!.parseFloat(s);
223
239
  `,
224
- output: dedent`
225
- import { Num, Result } from 'ts-data-forge';
226
- declare const s: string;
227
- const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
228
- const b = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
229
- `,
240
+ output: [
241
+ dedent`
242
+ import { Num, Result } from 'ts-data-forge';
243
+ declare const s: string;
244
+ const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
245
+ const b = Number!.parseFloat(s);
246
+ `,
247
+ dedent`
248
+ import { Num, Result } from 'ts-data-forge';
249
+ declare const s: string;
250
+ const a = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
251
+ const b = Result.unwrapOkOr(Num.safeParseFloat(s), Number.NaN);
252
+ `,
253
+ ],
230
254
  errors: [
231
255
  { messageId: 'useSafeParseFloat' },
232
256
  { messageId: 'useSafeParseFloat' },
@@ -98,8 +98,7 @@ describe('prefer-num-safe-parse-int', () => {
98
98
  const n = parseInt(s, 10);
99
99
  `,
100
100
  output: dedent`
101
- import { Result } from 'ts-data-forge';
102
- import { Num } from 'ts-data-forge';
101
+ import { Num, Result } from 'ts-data-forge';
103
102
 
104
103
  const s = "123";
105
104
  const n = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
@@ -162,12 +161,20 @@ describe('prefer-num-safe-parse-int through type wrappers', () => {
162
161
  const a = parseInt(s, 10 as const);
163
162
  const b = Number.parseInt(s!, 10 satisfies number);
164
163
  `,
165
- output: dedent`
166
- import { Num, Result } from 'ts-data-forge';
167
- declare const s: string;
168
- const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
169
- const b = Result.unwrapOkOr(Num.safeParseInt(s!), Number.NaN);
170
- `,
164
+ output: [
165
+ dedent`
166
+ import { Num, Result } from 'ts-data-forge';
167
+ declare const s: string;
168
+ const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
169
+ const b = Number.parseInt(s!, 10 satisfies number);
170
+ `,
171
+ dedent`
172
+ import { Num, Result } from 'ts-data-forge';
173
+ declare const s: string;
174
+ const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
175
+ const b = Result.unwrapOkOr(Num.safeParseInt(s!), Number.NaN);
176
+ `,
177
+ ],
171
178
  errors: [
172
179
  { messageId: 'useSafeParseInt' },
173
180
  { messageId: 'useSafeParseInt' },
@@ -180,12 +187,20 @@ describe('prefer-num-safe-parse-int through type wrappers', () => {
180
187
  const a = (parseInt as typeof parseInt)(s);
181
188
  const b = (Number as NumberConstructor)!.parseInt(s, 10);
182
189
  `,
183
- output: dedent`
184
- import { Num, Result } from 'ts-data-forge';
185
- declare const s: string;
186
- const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
187
- const b = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
188
- `,
190
+ output: [
191
+ dedent`
192
+ import { Num, Result } from 'ts-data-forge';
193
+ declare const s: string;
194
+ const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
195
+ const b = (Number as NumberConstructor)!.parseInt(s, 10);
196
+ `,
197
+ dedent`
198
+ import { Num, Result } from 'ts-data-forge';
199
+ declare const s: string;
200
+ const a = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
201
+ const b = Result.unwrapOkOr(Num.safeParseInt(s), Number.NaN);
202
+ `,
203
+ ],
189
204
  errors: [
190
205
  { messageId: 'useSafeParseInt' },
191
206
  { messageId: 'useSafeParseInt' },