Skip to content

Commit 1ed5674

Browse files
Copilotmrjf
andauthored
Widen Series method signatures to eliminate as-never casts in tests
Widen arithmetic methods to accept number | Series<Scalar> instead of T | Series<T>, comparison methods to accept Scalar | Series<Scalar>, and isin to accept readonly Scalar[]. This avoids literal type narrowing issues that previously required as-never casts in tests. Agent-Logs-Url: https://github.com/githubnext/tsessebe/sessions/8871403f-f41c-4311-a8fd-19f148d98d2d Co-authored-by: mrjf <180956+mrjf@users.noreply.github.com>
1 parent cada2ee commit 1ed5674

2 files changed

Lines changed: 45 additions & 39 deletions

File tree

src/core/series.ts

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,10 @@ export class Series<T extends Scalar = Scalar> {
214214

215215
// ─── arithmetic ───────────────────────────────────────────────────────────
216216

217-
private _scalarOp(other: T | Series<T>, fn: (a: number, b: number) => number): Series<number> {
217+
private _scalarOp(
218+
other: number | Series<Scalar>,
219+
fn: (a: number, b: number) => number,
220+
): Series<number> {
218221
const isScalar = !(other instanceof Series);
219222
if (isScalar) {
220223
const b = other as number;
@@ -229,7 +232,7 @@ export class Series<T extends Scalar = Scalar> {
229232
name: this.name,
230233
});
231234
}
232-
const o = other as Series<T>;
235+
const o = other as Series<Scalar>;
233236
if (o.size !== this.size) {
234237
throw new RangeError(
235238
`Cannot operate on Series of different sizes: ${this.size} vs ${o.size}`,
@@ -249,46 +252,49 @@ export class Series<T extends Scalar = Scalar> {
249252
}
250253

251254
/** Element-wise addition. */
252-
add(other: T | Series<T>): Series<number> {
255+
add(other: number | Series<Scalar>): Series<number> {
253256
return this._scalarOp(other, (a, b) => a + b);
254257
}
255258

256259
/** Element-wise subtraction. */
257-
sub(other: T | Series<T>): Series<number> {
260+
sub(other: number | Series<Scalar>): Series<number> {
258261
return this._scalarOp(other, (a, b) => a - b);
259262
}
260263

261264
/** Element-wise multiplication. */
262-
mul(other: T | Series<T>): Series<number> {
265+
mul(other: number | Series<Scalar>): Series<number> {
263266
return this._scalarOp(other, (a, b) => a * b);
264267
}
265268

266269
/** Element-wise division (true division, returns float). */
267-
div(other: T | Series<T>): Series<number> {
270+
div(other: number | Series<Scalar>): Series<number> {
268271
return this._scalarOp(other, (a, b) => a / b);
269272
}
270273

271274
/** Element-wise floor division. */
272-
floordiv(other: T | Series<T>): Series<number> {
275+
floordiv(other: number | Series<Scalar>): Series<number> {
273276
return this._scalarOp(other, (a, b) => Math.floor(a / b));
274277
}
275278

276279
/** Element-wise modulo. */
277-
mod(other: T | Series<T>): Series<number> {
280+
mod(other: number | Series<Scalar>): Series<number> {
278281
return this._scalarOp(other, (a, b) => a % b);
279282
}
280283

281284
/** Element-wise exponentiation. */
282-
pow(other: T | Series<T>): Series<number> {
285+
pow(other: number | Series<Scalar>): Series<number> {
283286
return this._scalarOp(other, (a, b) => a ** b);
284287
}
285288

286289
// ─── comparison ───────────────────────────────────────────────────────────
287290

288-
private _cmpOp(other: T | Series<T>, fn: (a: T, b: T) => boolean): Series<boolean> {
291+
private _cmpOp(
292+
other: Scalar | Series<Scalar>,
293+
fn: (a: Scalar, b: Scalar) => boolean,
294+
): Series<boolean> {
289295
const isScalar = !(other instanceof Series);
290296
if (isScalar) {
291-
const b = other as T;
297+
const b = other as Scalar;
292298
const newData = this._values.map((a) => fn(a, b));
293299
return new Series<boolean>({
294300
data: newData,
@@ -297,11 +303,11 @@ export class Series<T extends Scalar = Scalar> {
297303
name: this.name,
298304
});
299305
}
300-
const o = other as Series<T>;
306+
const o = other as Series<Scalar>;
301307
if (o.size !== this.size) {
302308
throw new RangeError(`Cannot compare Series of different sizes: ${this.size} vs ${o.size}`);
303309
}
304-
const newData = this._values.map((a, i) => fn(a, o._values[i] as T));
310+
const newData = this._values.map((a, i) => fn(a, o._values[i] as Scalar));
305311
return new Series<boolean>({
306312
data: newData,
307313
index: this.index,
@@ -310,15 +316,15 @@ export class Series<T extends Scalar = Scalar> {
310316
});
311317
}
312318

313-
eq(other: T | Series<T>): Series<boolean> {
319+
eq(other: Scalar | Series<Scalar>): Series<boolean> {
314320
return this._cmpOp(other, (a, b) => a === b);
315321
}
316322

317-
ne(other: T | Series<T>): Series<boolean> {
323+
ne(other: Scalar | Series<Scalar>): Series<boolean> {
318324
return this._cmpOp(other, (a, b) => a !== b);
319325
}
320326

321-
lt(other: T | Series<T>): Series<boolean> {
327+
lt(other: Scalar | Series<Scalar>): Series<boolean> {
322328
return this._cmpOp(other, (a, b) => {
323329
if (a === null || b === null) {
324330
return false;
@@ -327,7 +333,7 @@ export class Series<T extends Scalar = Scalar> {
327333
});
328334
}
329335

330-
le(other: T | Series<T>): Series<boolean> {
336+
le(other: Scalar | Series<Scalar>): Series<boolean> {
331337
return this._cmpOp(other, (a, b) => {
332338
if (a === null || b === null) {
333339
return false;
@@ -336,7 +342,7 @@ export class Series<T extends Scalar = Scalar> {
336342
});
337343
}
338344

339-
gt(other: T | Series<T>): Series<boolean> {
345+
gt(other: Scalar | Series<Scalar>): Series<boolean> {
340346
return this._cmpOp(other, (a, b) => {
341347
if (a === null || b === null) {
342348
return false;
@@ -345,7 +351,7 @@ export class Series<T extends Scalar = Scalar> {
345351
});
346352
}
347353

348-
ge(other: T | Series<T>): Series<boolean> {
354+
ge(other: Scalar | Series<Scalar>): Series<boolean> {
349355
return this._cmpOp(other, (a, b) => {
350356
if (a === null || b === null) {
351357
return false;
@@ -648,8 +654,8 @@ export class Series<T extends Scalar = Scalar> {
648654
// ─── set operations ───────────────────────────────────────────────────────
649655

650656
/** True when `value` exists in this Series. */
651-
isin(values: readonly T[]): Series<boolean> {
652-
const set = new Set<T>(values);
657+
isin(values: readonly Scalar[]): Series<boolean> {
658+
const set = new Set<Scalar>(values);
653659
return new Series<boolean>({
654660
data: this._values.map((v) => set.has(v)),
655661
index: this.index,

tests/core/series.test.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -99,30 +99,30 @@ describe("Series", () => {
9999
const a = new Series({ data: [1, 2, 3] });
100100
const b = new Series({ data: [4, 5, 6] });
101101

102-
it("add scalar", () => expect(a.add(10 as never).values).toEqual([11, 12, 13]));
103-
it("add series", () => expect(a.add(b as never).values).toEqual([5, 7, 9]));
104-
it("sub series", () => expect(b.sub(a as never).values).toEqual([3, 3, 3]));
105-
it("mul scalar", () => expect(a.mul(2 as never).values).toEqual([2, 4, 6]));
106-
it("div series", () => expect(b.div(a as never).values).toEqual([4, 2.5, 2]));
107-
it("mod", () => expect(b.mod(a as never).values).toEqual([0, 1, 0]));
108-
it("pow", () => expect(a.pow(2 as never).values).toEqual([1, 4, 9]));
109-
it("floordiv", () => expect(b.floordiv(a as never).values).toEqual([4, 2, 2]));
102+
it("add scalar", () => expect(a.add(10).values).toEqual([11, 12, 13]));
103+
it("add series", () => expect(a.add(b).values).toEqual([5, 7, 9]));
104+
it("sub series", () => expect(b.sub(a).values).toEqual([3, 3, 3]));
105+
it("mul scalar", () => expect(a.mul(2).values).toEqual([2, 4, 6]));
106+
it("div series", () => expect(b.div(a).values).toEqual([4, 2.5, 2]));
107+
it("mod", () => expect(b.mod(a).values).toEqual([0, 1, 0]));
108+
it("pow", () => expect(a.pow(2).values).toEqual([1, 4, 9]));
109+
it("floordiv", () => expect(b.floordiv(a).values).toEqual([4, 2, 2]));
110110

111111
it("throws when sizes differ", () => {
112112
const c = new Series({ data: [1, 2] });
113-
expect(() => a.add(c as never)).toThrow(RangeError);
113+
expect(() => a.add(c)).toThrow(RangeError);
114114
});
115115
});
116116

117117
describe("comparison", () => {
118118
const s = new Series({ data: [1, 2, 3] });
119119

120-
it("eq", () => expect(s.eq(2 as never).values).toEqual([false, true, false]));
121-
it("ne", () => expect(s.ne(2 as never).values).toEqual([true, false, true]));
122-
it("lt", () => expect(s.lt(2 as never).values).toEqual([true, false, false]));
123-
it("le", () => expect(s.le(2 as never).values).toEqual([true, true, false]));
124-
it("gt", () => expect(s.gt(2 as never).values).toEqual([false, false, true]));
125-
it("ge", () => expect(s.ge(2 as never).values).toEqual([false, true, true]));
120+
it("eq", () => expect(s.eq(2).values).toEqual([false, true, false]));
121+
it("ne", () => expect(s.ne(2).values).toEqual([true, false, true]));
122+
it("lt", () => expect(s.lt(2).values).toEqual([true, false, false]));
123+
it("le", () => expect(s.le(2).values).toEqual([true, true, false]));
124+
it("gt", () => expect(s.gt(2).values).toEqual([false, false, true]));
125+
it("ge", () => expect(s.ge(2).values).toEqual([false, true, true]));
126126
});
127127

128128
describe("filter", () => {
@@ -134,7 +134,7 @@ describe("Series", () => {
134134
});
135135

136136
it("filters by boolean Series", () => {
137-
const mask = s.gt(2 as never);
137+
const mask = s.gt(2);
138138
const result = s.filter(mask);
139139
expect(result.values).toEqual([3, 4, 5]);
140140
});
@@ -173,7 +173,7 @@ describe("Series", () => {
173173
it("nunique", () => expect(s.nunique()).toBe(5));
174174

175175
it("sum with nulls skips them", () => {
176-
const s2 = new Series({ data: [1, null, 2, null, 3] as never[] });
176+
const s2 = new Series({ data: [1, null, 2, null, 3] });
177177
expect(s2.sum()).toBe(6);
178178
});
179179

@@ -245,7 +245,7 @@ describe("Series", () => {
245245
describe("isin", () => {
246246
it("returns boolean mask", () => {
247247
const s = new Series({ data: [1, 2, 3, 4] });
248-
expect(s.isin([2, 4] as never[]).values).toEqual([false, true, false, true]);
248+
expect(s.isin([2, 4]).values).toEqual([false, true, false, true]);
249249
});
250250
});
251251

0 commit comments

Comments
 (0)