如何调用类型参数的静态方法?

问题描述 投票:0回答:1

考虑以下伪代码:

abstract class X {}

class Y extends X {
  static compare(a: Y, b: Y) {
    return a.id - b.id;
  }
}

class Z extends X {
  static compare(a: Z, b: Z) {
    return a.name.localCompare(b.name);
  }
}

function sort<T extends X>(items: T[]) {
  return items.sort(T.compare); //   <-- illegal
}


Y.sort([new Y(), new Y()]);     //  <-- should use Ys compare 
Z.sort([new Z(), new Z()]);     //  <-- should use Zs compare 

排序函数应利用用于调用它的类型的相应比较函数。这是行不通的,因为 T 不能这样使用。如何更改最后的通用函数以便我可以使用 Y 的静态比较函数?

(在任何人发表评论之前,请不要建议我如何简化整个事情并完全避免问题的解决方案。显然,上面是一个 MCVE 式的示例来说明问题,而不是我正在处理的完整代码。 )

javascript typescript static
1个回答
0
投票

理想情况下,您应该为您的

X
超类提供一个
static
方法,该方法仅允许其在该类的实例上进行操作。但这需要使用 多态
this
类型
,而 TypeScript 目前不支持
static
方法中的此类类型。请参阅 microsoft/TypeScript#5863 中长期存在的开放功能请求。直到并且除非它得到实施,我们将需要解决它。

常见的解决方法之一是使方法通用,并为其提供代表类似约束的

this
参数。因此静态方法只能在正确形状的类上调用。

因此,假设我们只想被允许在具有适当类型的

sort()
方法的类构造函数上调用
compare
。这种类型可能是

interface Comparator<T> {
  compare: (this: void, a: T, b: T) => number;
}

意味着我们要求类构造函数对于某些

Comparator<T>
来说是
T
。 (注意
void
this
上下文表示
compare
必须可调用,无需绑定到对象;如果我们愿意,可以放宽,但希望这足够好。)然后我们在
 上写 
sort()
 X
像这样:

abstract class X {
  static sort<T extends X>(this: Comparator<T>, items: T[]) {
    return items.sort(this.compare);
  }
}

编译干净;让我们测试一下:

class Y extends X {
  id: number = 0;
  static compare(a: Y, b: Y) {
    return a.id - b.id;
  }
}

class Z extends X {
  name: string = "";
  static compare(a: Z, b: Z) {
    return a.name.localeCompare(b.name);
  }
}

Y.sort([new Y(), new Y()]); // okay
Z.sort([new Z(), new Z()]); // okay
Z.sort([new Y(), new Z()]); // error
// ---> ~~~~~~~ Y is not Z
X.sort([new Y(), new Z()]); // error
// <-- compare is missing from X

看起来不错。支持您想要的呼叫,拒绝不需要的呼叫。您只能在

Z.sort()
实例数组上调用
Z
,并且根本不允许直接调用
X.sort()
,因为
X
根本不是
Comparator

Playground 代码链接

© www.soinside.com 2019 - 2024. All rights reserved.