簡體   English   中英

類型化數組和聯合類型

[英]Typed arrays and union types

我經常使用類型化數組,我的很多函數真的應該可以使用任何類型的數組(例如,對Uint8ArrayFloat32Array )。 有時,我只能使用一個簡單的類型聯合,但我常常遇到同樣的錯誤。

一個簡單的例子:

type T1 = Uint8Array;
type T2 = Int8Array;
type T3 = Uint8Array | Int8Array;

// No problems here:
const f1 = (arr: T1) => arr.reduce((sum, value) => sum + value);
const f2 = (arr: T2) => arr.reduce((sum, value) => sum + value);

// Does not work:
const f3 = (arr: T3) => arr.reduce((sum, value) => sum + value);

f3的錯誤是:

Cannot invoke an expression whose type lacks a call signature. Type '
{
    (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number): number;
    (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue: number): number;
    <U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U): U;
} | {
    (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number): number;
    (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue: number): number;
    <U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U; 
}' has no compatible call signatures.ts(2349)

根據文件

如果我們有一個具有union類型的值,我們只能訪問union中所有類型共有的成員。

我在這里使用reduce的方式對於所有數組都是通用的,但我猜測問題是可選的第4個參數(對於Uint8Array.prototype.reduceUint8Array但對於Int8Array.prototype.reduceInt8Array )。

有一個簡單的解決方法嗎? 或者我是否需要為每個mapreducefilter編寫泛型實現?

調用函數聯合一直存在問題。 直到最近,規則是根本不允許調用,但是由於允許3.3( PR )調用以及一些警告。 你在這里遇到的最大問題是,如果工會的成員都有通用簽名,那么仍然不允許通話。 因此,例如,在簡單的數組一個forEach可以被稱為(在其上沒有通用類型參數),而reduce不能稱為(因為二者reducestring[]並從number[]具有一般類型參數):

declare let o: string[] | number[];
o.forEach((e: number | string) => console.log(e)); // ok 
o.reduce((e: number | string, r: number | string) => e + ' ' + r) //err

這意味着很難使用數組類型的並集,並且只允許調用一小組方法(大多數Array方法都有泛型類型參數)。

這也適用於Uint8ArrayInt8Array ,雖然不繼承數組有大多數相同的方法。

這里沒有好的解決方案,最簡單的解決方法是將變量斷言為其中一種類型並繼續使用(假設您不使用array回調參數,它應該沒問題)

const f3 = (arr: T3) => (arr as Uint8Array).reduce((sum, value, array /* no good inferred to Uint8Array */) => sum + value);

或者回到您可以調用的其中一個函數

const f4 = (arr: T3) => {
    let sum = 0;
    (arr as Uint8Array).forEach((val)=> sum + val)
} 

有簡單的解決方法。 使用通用方法簽名聲明接口

type T3 = Uint8Array | Int8Array;

interface HasReduce {
    reduce(c: (p: number, n: number) => number): number; // common callback signture with 2 arguments
}

function someLogic(arr: HasReduce): number { 
    return arr.reduce((sum, value) => sum + value);
}

declare var v : T3;
someLogic(v); // OK

所以你可以聲明HasMap,HasFilter並將它們組合起來。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM