type Parent = {
fun<T>(a: T, b: string):void
}
type ChildFunArgs = Parameters<Parent['fun']<number>> // got an error
如果上面的代码可以运行,那么我可以这样做:
const childFunArgs: ChildFunArgs = [1, '1']
答案 0 :(得分:2)
没有高阶类型操纵可完全在类型系统中自动为您执行此操作。
如果您可以接受对运行时影响较小(意味着它会发出一些JS代码)并且外观丑陋的类型修改,请使用和(如果您使用的是TypeScript 3.4及更高版本),则可以您的类型如下:
const dummyParams =
((x => () => x) as <A extends any[]>(
f: (...args: A) => any) => () => A
)(null! as Parent['fun'])<number>();
type ChildFunArgs = typeof dummyParams
// type ChildFunArgs = [number, string]
您可以验证ChildFunArgs
是您期望的类型。在运行时,发出的代码本质上是
const dummyParams = ((x => () => x))(null)();
与
具有相同的作用const dummyParams = null;
因此对运行时有影响,但影响很小。
这些丑陋的东西如何工作?我们正在欺骗编译器以为我们拥有这样的功能:
declare function params<A extends any[]>(f: (...args: A)=>any): () => A;
此假设的params()
函数将接受函数参数f
,并返回一个新的零参数函数,该函数返回一个类型为f
的参数类型的元组。嗯,这令人困惑。我的意思是params((x: string, y: boolean)=>123)
将返回类型为() => [string, boolean]
的新函数。这样的功能基本上是不可能实现的,但我们不必真正实现它。
然后我们假设我们有一个fun
的{{1}}方法类型的值:
Parent
我们在其上拨打 declare const parentFun: Parent['fun'];
:
params
由于最近的improvements in higher-order function handling,编译器推断const paramsParentFun = params(parentFun);
// const paramsParentFun: <T>() => [T, string]
的类型为paramsParentFun
。现在,您可以假装调用 this 函数,并为<T>() => [T, string]
手动指定number
:
T
瞧!您会找到想要的东西。
上面的较短代码与此相同,但是它使用type assertions向编译器撒谎说明这些其他函数和值的存在,从而使发出的JavaScript不会产生额外的混乱。
好的,希望能有所帮助。祝你好运!
答案 1 :(得分:0)
如果您使用接口而不是Parent
的类型,则可以。
它看起来像这样:
interface Parent<T> {
fun(a: T, b: string):void
}
type ChildFunArgs = Parameters<Parent<number>['fun']>
const childFunArgs: ChildFunArgs = [1, '1']
您可以看到它在here下工作。