在一个库中,我有一个helper函数,它可以处理任何类型的数组,现在我想扩展它来接受typed arrays,但是我找不到一个公共基类,类型化数组也不是泛型的,这是我目前为止为泛型数组和一个类型化数组编写的代码:
public static copyOf(original: Int32Array, newLength: number): Int32Array;
public static copyOf<T>(original: T[], newLength: number): T[];
public static copyOf<T>(original: T[] | Int32Array, newLength: number): T[] | Int32Array {
if (original instanceof Int32Array) {
if (newLength < original.length) {
return original.slice(0, newLength);
}
if (newLength === original.length) {
return original.slice();
}
const result = new Int32Array(newLength);
result.set(original);
return result;
} else {
if (newLength < original.length) {
return original.slice(0, newLength);
}
if (newLength === original.length) {
return original.slice();
}
const result = new Array<T>(newLength);
result.splice(0, 0, ...original);
return result;
}
}
然而,这种方法需要为每个类型化数组类型添加一个自己的分支,这将挫败泛型的思想。如何以更紧凑的方式实现这一点?
1条答案
按热度按时间blmhpbnm1#
首先是类型,因为这是TypeScript。目前没有一个内置类型对应于类型化数组;请参见microsoft/TypeScript#15402。但是没有什么可以阻止您将自己的类型定义为相关单个类型的联合。下面是一种可能性:
我没有在这里包括
BigInt64Array
或BigUint64Array
,因为它们的行为与其他的不完全相同(您需要bigint
而不是number
),但是如果需要,您可以添加它们。现在来看看实现。一种方法是使用传入的类型化数组的
constructor
property来获取正确的类构造函数,并使用它来构造一个新示例。TypeScript不会乐意这样做。因为它不对强类型constructor
属性建模(参见ms/TS#3841中关于这个的详细讨论)......所以我们需要使用类型Assert来说服编译器它是可接受的。可能是这样的:
这里我没有检查
instanceof
来检查值是否是特定类型的数组,而是使用theArray.isArray()
method来检查值 * 不是 * 内置数组。(Also注意,我不得不改变the
splice()
method,它 * insert * things,导致结果数组比您预期的要长。)如果需要支持
BigInt64Array
和BigUint64Array
,那么必须在result.set(original);
行添加类型Assert以防止错误。让我们确保它的工作:
看起来不错。
Playground代码链接