From 97b579b6573f124b80f561d0ef5097e0f9f2e338 Mon Sep 17 00:00:00 2001 From: Trevor Manz Date: Tue, 3 Dec 2024 17:26:22 -0500 Subject: [PATCH] Support TypeScript 5.6 and 5.7 (#241) TypeScript 5.7 made TypeArray objects generic over an `ArrayBufferLike` source. We only use `ArrayBuffer` internally, so isdeally we would be explicit about the generic parameter in our return types. However, older versions of TS will fail with an explicit generic parameter (i.e., `Uint8Array`). The biggest issue is a mismatch between `ndarray` types and our own. This change vendors the types for `ndarray`, to align them with our own. --- package.json | 2 +- packages/core/src/codecs/vlen-utf8.ts | 4 +- packages/indexing/__tests__/setter.test.ts | 43 +++++----- packages/ndarray/package.json | 1 - packages/ndarray/src/missing-types.d.ts | 89 +++++++++++++++++++++ packages/typedarray/__tests__/index.test.ts | 4 +- packages/typedarray/src/index.ts | 6 +- pnpm-lock.yaml | 17 +--- 8 files changed, 124 insertions(+), 42 deletions(-) create mode 100644 packages/ndarray/src/missing-types.d.ts diff --git a/package.json b/package.json index 30c21979..b3a41a29 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "@svitejs/changesets-changelog-github-compact": "^1.2.0", "@types/node": "^22.10.1", "publint": "^0.2.12", - "typescript": "5.6.3", + "typescript": "5.7.2", "vitest": "^2.1.8" }, "packageManager": "pnpm@9.7.0" diff --git a/packages/core/src/codecs/vlen-utf8.ts b/packages/core/src/codecs/vlen-utf8.ts index ac8fcfce..1f46b572 100644 --- a/packages/core/src/codecs/vlen-utf8.ts +++ b/packages/core/src/codecs/vlen-utf8.ts @@ -26,7 +26,9 @@ export class VLenUTF8 { for (let i = 0; i < data.length; i++) { let item_length = view.getUint32(pos, true); pos += 4; - data[i] = decoder.decode(bytes.buffer.slice(pos, pos + item_length)); + // @ts-expect-error - we know this is an ArrayBuffer, TS just isn't smart enough to know it's not a SharedArrayBuffer + let buffer: ArrayBuffer = bytes.buffer; + data[i] = decoder.decode(buffer.slice(pos, pos + item_length)); pos += item_length; } return { data, shape: this.#shape, stride: this.#strides }; diff --git a/packages/indexing/__tests__/setter.test.ts b/packages/indexing/__tests__/setter.test.ts index 8f8c9fd9..7cd8f334 100644 --- a/packages/indexing/__tests__/setter.test.ts +++ b/packages/indexing/__tests__/setter.test.ts @@ -36,6 +36,7 @@ function to_c({ data, shape, stride }: Chunk): Chunk { let size = shape.reduce((a, b) => a * b, 1); // @ts-expect-error - We know constructor exists on TypedArray let out = ndarray(new data.constructor(size), shape); + // @ts-expect-error - ndarray types are a mismatch with ours but this operation is safe assign(out, ndarray(data, shape, stride)); return out; } @@ -59,7 +60,7 @@ describe("setter", () => { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -79,7 +80,7 @@ describe("setter", () => { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -91,7 +92,7 @@ describe("setter", () => { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, @@ -103,7 +104,7 @@ describe("setter", () => { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, @@ -115,7 +116,7 @@ describe("setter", () => { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 4, 3, @@ -136,7 +137,7 @@ describe("setter", () => { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - + 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, @@ -150,7 +151,7 @@ describe("setter", () => { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - + 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, @@ -190,7 +191,7 @@ describe("setter", () => { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - + 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, @@ -222,7 +223,7 @@ describe("setter", () => { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, - + 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, @@ -254,7 +255,7 @@ describe("setter", () => { 2, 0, 2, 0, 0, 0, 0, 0, 2, 0, 2, 0, - + 2, 0, 2, 0, 0, 0, 0, 0, 2, 0, 2, 0, @@ -274,7 +275,7 @@ describe("setter", () => { 2, 0, 2, 0, 0, 0, 0, 0, 2, 0, 2, 0, - + 2, 0, 2, 0, 0, 0, 0, 0, 2, 0, 2, 0, @@ -318,7 +319,7 @@ describe("setter", () => { 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, - + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -334,7 +335,7 @@ describe("setter", () => { 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, - + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -378,7 +379,7 @@ describe("setter", () => { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, - + 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, @@ -439,14 +440,14 @@ describe("setter", () => { setter.set_from_chunk(dest, src, mapping); // biome-ignore format: the array should not be formatted expect(to_c(dest).data).toStrictEqual(new Float32Array([ - 0, 2, 0, 0, - 0, 0, 0, 0, - 0, 2, 0, 0, + 0, 2, 0, 0, + 0, 0, 0, 0, + 0, 2, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - ])); + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + ])); }); it("set_from_chunk - dest=C order, src=F order", async () => { diff --git a/packages/ndarray/package.json b/packages/ndarray/package.json index 46c2e827..82474a8b 100644 --- a/packages/ndarray/package.json +++ b/packages/ndarray/package.json @@ -11,7 +11,6 @@ } }, "dependencies": { - "@types/ndarray": "^1.0.11", "@types/ndarray-ops": "^1.2.4", "@zarrita/core": "workspace:^", "@zarrita/indexing": "workspace:^", diff --git a/packages/ndarray/src/missing-types.d.ts b/packages/ndarray/src/missing-types.d.ts new file mode 100644 index 00000000..4b434e9f --- /dev/null +++ b/packages/ndarray/src/missing-types.d.ts @@ -0,0 +1,89 @@ +declare module "ndarray" { + declare function ndarray>( + data: D, + shape?: number[], + stride?: number[], + offset?: number, + ): ndarray.NdArray; + + declare namespace ndarray { + interface NdArray> { + data: D; + shape: number[]; + stride: number[]; + offset: number; + dtype: DataType; + size: number; + order: number[]; + dimension: number; + get(...args: number[]): Value; + set(...args: number[]): Value; + index(...args: number[]): Value; + lo(...args: number[]): NdArray; + hi(...args: number[]): NdArray; + step(...args: number[]): NdArray; + transpose(...args: number[]): NdArray; + pick(...args: Array): NdArray; + T: NdArray; + } + + interface GenericArray { + get(idx: number): T; + set(idx: number, value: T): void; + length: number; + } + + // biome-ignore lint/suspicious/noExplicitAny: not our library + type Data = T extends number + ? GenericArray | T[] | TypedArray + : T extends bigint + ? GenericArray | T[] | BigInt64Array | BigUint64Array + : GenericArray | T[]; + + type TypedArray = + | Int8Array + | Int16Array + | Int32Array + | Uint8Array + | Uint8ClampedArray + | Uint16Array + | Uint32Array + | Float32Array + | Float64Array; + + type Value = D extends + | GenericArray + // biome-ignore lint/suspicious/noRedeclare: not our library + | Record + ? T + : never; + + type DataType = D extends Int8Array + ? "int8" + : D extends Int16Array + ? "int16" + : D extends Int32Array + ? "int32" + : D extends Uint8Array + ? "uint8" + : D extends Uint8ClampedArray + ? "uint8_clamped" + : D extends Uint16Array + ? "uint16" + : D extends Uint32Array + ? "uint32" + : D extends Float32Array + ? "float32" + : D extends Float64Array + ? "float64" + : D extends BigInt64Array + ? "bigint64" + : D extends BigUint64Array + ? "biguint64" + : D extends GenericArray + ? "generic" + : "array"; + } + + export = ndarray; +} diff --git a/packages/typedarray/__tests__/index.test.ts b/packages/typedarray/__tests__/index.test.ts index 3cbdb3e7..b7701ac8 100644 --- a/packages/typedarray/__tests__/index.test.ts +++ b/packages/typedarray/__tests__/index.test.ts @@ -188,7 +188,9 @@ describe("ByteStringArray", () => { let data = new TextEncoder().encode( "Hello\x00world!\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", ); - let arr = new ByteStringArray(2, data.buffer, 3, 4); + // @ts-expect-error - we know this is an ArrayBuffer, TS just isn't smart enough to know it's not a SharedArrayBuffer + let buffer: ArrayBuffer = data.buffer; + let arr = new ByteStringArray(2, buffer, 3, 4); expect({ length: arr.length, BYTES_PER_ELEMENT: arr.BYTES_PER_ELEMENT, diff --git a/packages/typedarray/src/index.ts b/packages/typedarray/src/index.ts index 65118704..a155464b 100644 --- a/packages/typedarray/src/index.ts +++ b/packages/typedarray/src/index.ts @@ -31,7 +31,7 @@ export class BoolArray { } get buffer(): ArrayBuffer { - return this.#bytes.buffer; + return this.#bytes.buffer as ArrayBuffer; } get length(): number { @@ -106,7 +106,7 @@ export class ByteStringArray { } get buffer(): ArrayBuffer { - return this._data.buffer; + return this._data.buffer as ArrayBuffer; } get length(): number { @@ -198,7 +198,7 @@ export class UnicodeStringArray { } get buffer(): ArrayBuffer { - return this.#data.buffer; + return this.#data.buffer as ArrayBuffer; } get length(): number { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b3183ac8..756c79ad 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,8 +24,8 @@ importers: specifier: ^0.2.12 version: 0.2.12 typescript: - specifier: 5.6.3 - version: 5.6.3 + specifier: 5.7.2 + version: 5.7.2 vitest: specifier: ^2.1.8 version: 2.1.8(@types/node@22.10.1) @@ -81,9 +81,6 @@ importers: packages/ndarray: dependencies: - '@types/ndarray': - specifier: ^1.0.11 - version: 1.0.14 '@types/ndarray-ops': specifier: ^1.2.4 version: 1.2.7 @@ -1388,11 +1385,6 @@ packages: tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - typescript@5.6.3: - resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} - engines: {node: '>=14.17'} - hasBin: true - typescript@5.7.2: resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} engines: {node: '>=14.17'} @@ -2793,10 +2785,7 @@ snapshots: tr46@0.0.3: {} - typescript@5.6.3: {} - - typescript@5.7.2: - optional: true + typescript@5.7.2: {} undici-types@6.20.0: {}