MethodOf类型不能用于调用方法



我想动态生成一些测试,为此我必须调用具有要调用的方法名称的方法,然后完成所有测试设置并调用该方法。

我用createTest('methodName')代替it('methodName', () => ...lotsOfBoringStuff...)

为此,我想适当地键入方法,所以我有自动完成,并确定,我只调用正确的方法。

我设法拼凑了一些"应该工作"的东西,但是TS确实抱怨不兼容的类型:

type MethodOf<T> = {
  [P in keyof T]: T[P] extends () => unknown ? P : never;
}[keyof T];
function doStuff<T, N extends MethodOf<T>>(t: T, method: N): unknown {
  const meth: () => unknown = t[method]; // <-- boom: {} cannot be assigned to () => unknown
  return meth();
}
const t = {
  abc: 'str',
  foobar: () => 1,
};
doStuff(t, 'foobar');  // <-- works as expected + autocompletion
type T1 = typeof t;
type N1 = MethodOf<T1>; // 'foobar'
type M1 = T1[N1]; // () => number // <-- works as expected

为什么TS检测不到T[MethodOf<T>]实际上是一个可调用的方法?在分配之前,是否有另一种选择将其转换为any ?

我用的是typescript 4.6.

如果我们这样定义类型OnlyMethods:

type OnlyMethods<T> = Pick<T, MethodOf<T>>;

然后将doStuff的签名修改为:

function doStuff<T extends OnlyMethods<T>, N extends MethodOf<T>>(t: T, method: N): unknown {

函数体现在可以工作了:

function doStuff<T extends OnlyMethods<T>, N extends MethodOf<T>>(t: T, method: N): unknown {
  const meth = t[method]; // not even a type annotation is needed!
  return meth();          // it just WORKS
}

我相信这个反直觉的解决方案是有效的,因为T现在只是方法,而N只是对应于方法的键,这意味着T[N]总是一个方法。

游乐场

最新更新