我认为标题无法真正传达我在这里想要做的事情。但是我们还是要走了。
我有一个函数,它将返回另一个函数。问题是返回哪种类型的函数取决于我在第一个函数中输入的参数。看起来像这样
Function('function2')('what-ever-parameter-of-function2')
Function('function3')('what-ever-parameter-of-function3')
我想做的是,当我点击第一个()时,它将提供'function2'或'function3'< / strong>,并在此基础上,当我点击第二个()时,它会自动选择已经在第一个()上选择的确切功能的参数。 / p>
我的情况实际上比这要复杂得多,但是概念基本上就是这个。 This is what I'm trying out.
在此示例中,我尝试在第一个()中具有property1或property2,并基于第二个()中的(function1和function2)或(function3和function4) 已注释掉的代码仅是实验,我能够使其在property1或property2上自动完成,但是在第二个()中没有自动完成的约束 您将在操场上看到一些错误,忽略最后一个,我只是懒惰地编写了该函数的实际实现。我有两个问题。 键入'Mutations [M] [string] |变异[M] [数字] |
不能将Mutations [M] [symbol]'分配给类型'(... args:any)=>
任何 我只是不明白为什么打字稿将K视为 如果将鼠标悬停在 K 上,您会看到它的类型为
string | number | symbol
const testO: TestT = {
commit: function(name) {
return (K, P) => 'void';
}
}
never
。我有点理解,因为“ property1”和“ property2”内部没有通用功能。但这对我来说毫无意义。我想要的只是在commit(name: 'property1' |'property2')
函数中,当我键入name
参数时,它将name
传递到下一个函数中,该函数将确定要返回的设置函数>
答案 0 :(得分:0)
您的解决方案离我们并不遥远。
您可以使用几个辅助提取器来正确排列所有内容,例如
type ExtractParams<T> = T extends (a: infer K) => any ? K : never
type ExtractReturn<T> = T extends (a: any) => infer K ? K : never
现在,您的Commit
和TestT
类型变为
type Mutations = {
'property1': {
f: (param: string) => void;
g: (param: string) => string;
},
'property2': {
h: (param: number) => void;
j: (param: number) => string;
}
}
type Commit<M extends keyof Mutations> =
<K extends keyof Mutations[M], P extends Mutations[M][K]>(
key: K,
payload: ExtractParams<P>
) => ExtractReturn<P>
type TestT = {
commit: <K extends keyof Mutations>(
name: K
) => Commit<K>
}
一切都很好
const a = test.commit('property1')(
"f", "hello" // OK
) // void
const b = test.commit('property2')(
"h", 1 // OK
) // void
const c = test.commit('property2')(
"j", 1 // OK
) // string