[英]Typed arrays and union types
我經常使用類型化數組,我的很多函數真的應該可以使用任何類型的數組(例如,對Uint8Array
或Float32Array
)。 有時,我只能使用一個簡單的類型聯合,但我常常遇到同樣的錯誤。
一個簡單的例子:
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.reduce
是Uint8Array
但對於Int8Array.prototype.reduce
是Int8Array
)。
有一個簡單的解決方法嗎? 或者我是否需要為每個map
, reduce
, filter
編寫泛型實現?
調用函數聯合一直存在問題。 直到最近,規則是根本不允許調用,但是由於允許3.3( PR )調用以及一些警告。 你在這里遇到的最大問題是,如果工會的成員都有通用簽名,那么仍然不允許通話。 因此,例如,在簡單的數組一個forEach
可以被稱為(在其上沒有通用類型參數),而reduce
不能稱為(因為二者reduce
從string[]
並從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方法都有泛型類型參數)。
這也適用於Uint8Array
和Int8Array
,雖然不繼承數組有大多數相同的方法。
這里沒有好的解決方案,最簡單的解決方法是將變量斷言為其中一種類型並繼續使用(假設您不使用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.