类泛型类型的打字稿方法允许任何
Posted
技术标签:
【中文标题】类泛型类型的打字稿方法允许任何【英文标题】:Typescript method of class generic type allows any 【发布时间】:2021-06-09 21:40:46 【问题描述】:几乎有一个小例外,我的约束似乎仍然允许任何例外。 谁能告诉我我在这里缺少什么。
用例:
class A
public b()
public c:number = 0;
public d:any;
;
当前实现:
function methodOfClass<
T extends new (...args: any[]): any; & Function,
M extends (this:T, ...args:any[]) => any =
[K in keyof T]: T[K] extends (this:T, ...args:any[]) => any
? T[K]
: never
[keyof T]
>(ctor:T, method:M, args?:Parameters<M>) : ReturnType<M>
return method.call(ctor, args ?? []);
const m0 = methodOfClass(A, A.prototype.b); // correct
const m1 = methodOfClass(A, A.prototype.c); // correct
const m2 = methodOfClass(A, A.prototype.d); // incorrect :-(
受此线程的启发,我还管理了以下内容,但找不到合适的使用方法? How to create a type excluding instance methods from a class in typescript?
type Methods<T> = Omit<T,
[K in keyof T]: T[K] extends (this:T, ...args:any[]) => any
? never
: K
[keyof T]>;
type M = Methods<A>; // correct
【问题讨论】:
any 可以分配给任何东西 正如@RobertoZvjerković 所说,any
可以是任何东西。它可以是一种方法,也可以是一种属性。所以这是预期的行为。您的methodOfClass
输入没有错误。唯一的“错误”是在课堂上使用any
!
我完全同意使用 any 违背了首先拥有类型的目的,是的。
【参考方案1】:
any
可以是 Function
any
可以是任何东西,包括Function
。您的methodOfClass
函数无法知道您打算 d
成为一个属性。 d
是一个函数就很好了。
const a = new A();
a.d = () => "hello world"; // no error because `() => string` is assignable to `any`
换句话说,您看到的m2
的结果是预期的行为,它不是“不正确的”。 any
表示d
可以 是一个函数,并且可以使用任何参数调用它。所以这也很好:
const m3 = methodOfClass(A, A.prototype.d, ["something", 999]);
显然这样做有很大的运行时错误的可能性。
这里唯一的解决方案是不要在类属性上使用any
!
不要让args
成为可选项
与any
的问题无关,我强烈建议您更改调用方法的方式以避免运行时错误。如果函数需要参数但您只使用默认的[]
,那么您将遇到问题。
(ctor: T, method: M, ...args: Parameters<M>): ReturnType<M>
return method.call(ctor, ...args);
使用...
允许您在不需要参数时不传递任何内容,但要求您传递所有必需的参数(作为单独的参数传递给methodOfClass
,而不是作为数组)。
class E
public e(n: number): number
return n + 1;
;
const m0 = methodOfClass(A, A.prototype.b); // this is still the same
console.log(m0); // undefined
const m3 = methodOfClass(E, E.prototype.e, 6); // but here we need a `number`
console.log(m3); // 7
const m4 = methodOfClass(E, E.prototype.e); // error because args missing
Typescript Playground Link
【讨论】:
spread/rest 确实更干净,感谢您与我一起思考。以上是关于类泛型类型的打字稿方法允许任何的主要内容,如果未能解决你的问题,请参考以下文章