TypeScript:TypedArray的泛型类型定义

shu*_*ksh 5 javascript generics typed-arrays typescript

我试图通过将任意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);
};
Run Code Online (Sandbox Code Playgroud)

虽然代码按预期工作,但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

Nit*_*mer 6

这不是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 (size: number): 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;
};
Run Code Online (Sandbox Code Playgroud)

(游乐场代码)