为特定类型扩展 TypeScript 数组

3

我知道如何为任何类型扩展数组:

declare global {
  interface Array<T> {
    remove(elem: T): Array<T>;
  }
}

if (!Array.prototype.remove) {
  Array.prototype.remove = function<T>(this: T[], elem: T): T[] {
    return this.filter(e => e !== elem);
  }
}

来源: 在TypeScript中扩展数组

但是是否有一种方法仅针对特定类型扩展数组?比如仅针对类型为User的数组 -> Array<User>

我想创建一个扩展方法,例如.toUsersMap(),并且仅对具有类型User的数组显示该方法。

2个回答

3
您可以实现类似的行为:
type User = {
  tag: 'User'
}

interface Array<T> {
  toUsersMap: T extends User ? (elem: T) => Array<T> : never
}

declare var user: User;

const arr = [user]

arr.toUsersMap(user) // ok

const another_array = [{ notUser: true }]

another_array.toUsersMap() // This expression is not callable

如果 T 参数不扩展 User,TS 将不允许使用 toUsersMap

Playground


1
你也可以像这样使用a this parameter - jcalz
1
@jcalz,我相信你的解决方案比我的好得多。请提供一个答案。 - captain-yossarian from Ukraine

2
我认为没有完全抑制 IntelliSense 在 Array 上提示 toUsersMap() 的方法,但你绝对可以使调用 arr.toUsersMap() 成为编译器错误,除非 arr 可以分配给 Array<User>。其中一种方法是给 toUsersMap() 方法添加一个this 参数
interface Array<T> {
  toUsersMap(this: Array<User>): Map<string, User>;
}

现在编译器将要求只能使用可分配给 Array<User> 的对象作为 this 上下文来调用 toUsersMap()
interface User {
  username: string;
}
const arr = [{ username: "foo" }, { username: "bar" }];
arr.toUsersMap() // okay, no error

const another_array = ["hello", 123];
another_array.toUsersMap() // error, 
//~~~~~~~~~~~ <--
// The 'this' context of type '{ notUser: boolean; }[]' is 
// not assignable to method's 'this' of type 'User[]'

代码操场链接


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接