TypeScript:TypedArray的泛型类型定义

问题描述 投票:5回答:3

我试图通过将任意TypedArray作为输入来编写一个扩展/收缩TypedArray的函数,并返回一个具有不同大小的新的同型TypedArray并将原始元素复制到其中。

例如,当你通过新的new Uint32Array([1,2,3])大小的5时,它将返回new Uint32Array([1,2,3,0,0])

export const resize = <T>(
    source: ArrayLike<T>, newSize: number,
): ArrayLike<T> => {
    if (!source.length) { return new source.constructor(newSize); }
    newSize = typeof newSize === "number" ? newSize : source.length;
    if (newSize >= source.length) {
        const buf = new ArrayBuffer(newSize * source.BYTES_PER_ELEMENT);
        const arr = new source.constructor(buf);
        arr.set(source);
        return arr;
    }
    return source.slice(0, newSize);
};

虽然代码按预期工作,但TSC抱怨1)ArrayType没有BYTES_PER_ELEMENTslice,以及2)Cannot use 'new' with an expression whose type lacks a call or construct signature用于语句new source.constructor()

有没有办法为TSC了解我的意图的功能指定类型接口?

对于1),我理解ArrayLike没有为TypedArray定义的接口,但是单个类型的数组似乎不从公共类继承...例如,我可以使用const expand = (source: <Uint32Array|Uint16Array|...>): <Uint32Array|Uint16Array|...> => {}而不是使用泛型。但它失去了返回类型的上下文是源数组的相同类型。

对于2)我对如何解决这个错误毫无头绪。 TSC似乎有理由抱怨源的构造函数缺少类型信息。但是如果我能为1)传递正确的类型,我认为2)也会消失。

ref)https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray

javascript generics typescript typed-arrays
3个回答
5
投票

这不是beautitiful,但它的工作原理:

type TypedArray = ArrayLike<any> & {
    BYTES_PER_ELEMENT: number;
    set(array: ArrayLike<number>, offset?: number): void;
    slice(start?: number, end?: number): TypedArray;
};
type TypedArrayConstructor<T> = {
    new (): T;
    new (buffer: ArrayBuffer): T;
    BYTES_PER_ELEMENT: number;
}

export const resize = <T extends TypedArray>(source: T, newSize: number): T => {
    if (!source.length) {
        return new (source.constructor as TypedArrayConstructor<T>)();
    }

    newSize = typeof newSize === "number" ? newSize : source.length;

    if (newSize >= source.length) {
        const buf = new ArrayBuffer(newSize * source.BYTES_PER_ELEMENT);
        const arr = new (source.constructor as TypedArrayConstructor<T>)(buf);
        arr.set(source);
        return arr;
    }
    return source.slice(0, newSize) as T;
};

(Qazxswpoi)


2
投票

我抓住@Nitzan的答案并按摩它直到所有的类型演员都消失了,但不幸的是这个解决方案受到了code in playground的影响,似乎没有没有类型转换的解决方法。我发布代码以供将来参考。

警告:此代码自2017/05/16起未编译。

untyped constructor property issue here

2
投票

您只需在声明文件中定义通用interface GenericTypedArray<T> extends ArrayLike<number> { BYTES_PER_ELEMENT: number; set(array: ArrayLike<number>, offset?: number): void; slice(start?: number, end?: number): T; constructor: GenericTypedArrayConstructor<T>; } interface GenericTypedArrayConstructor<T> { new (): T; new (buffer: ArrayBuffer): T; } export function resize<T extends GenericTypedArray<T>>(source: T, newSize: number): T { if (!source.length) { return new source.constructor(); } newSize = typeof newSize === "number" ? newSize : source.length; if (newSize >= source.length) { const buf = new ArrayBuffer(newSize * source.BYTES_PER_ELEMENT); const arr = new source.constructor(buf); arr.set(source); return arr; } return source.slice(0, newSize); }; class DummyArray { constructor(); constructor(buffer: ArrayBuffer); constructor(array: ArrayLike<number>); constructor(arg?) { } // Hack to have a typed constructor property, see https://github.com/Microsoft/TypeScript/issues/3841 'constructor': typeof DummyArray; BYTES_PER_ELEMENT: number; length: number; [index: number]: number; set(array: ArrayLike<number>, offset?: number): void { } slice(start?: number, end?: number): this { return this; } static BYTES_PER_ELEMENT: number; } // How it intended to work resize(new DummyArray([1, 2, 3]), 5); // How it fails to typecheck // Types of property 'constructor' are incompatible. // Type 'Function' is not assignable to type 'GenericTypedArrayConstructor<Uint8Array>'. resize(new Uint8Array([1, 2, 3]), 5); 即可。

1-在您的应用中创建名为TypedArray的文件。

2-添加以下行:

extras.d.ts

然后通用type TypedArray = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array; 类型将在整个项目中可用。您可以使用此TypedArray文件继续声明在整个应用程序中使用的更多自定义类型。

© www.soinside.com 2019 - 2024. All rights reserved.