Typescript从对象的一个键中推断信息
拥有 我试图使这个实现工作,当我尝试使用fn时,在我的b方法中得到类型错误和intelissense。所以基本上fn第一个参数是propOne的关键之一,而fn第二个参数是基于您选择的方法。因为在这个示例中,我选择了带有“methodOne”的fn,所以第二个参数被推断为number,因为methodOne的arg2是number类型Typescript从对象的一个键中推断信息,typescript,generics,types,Typescript,Generics,Types,拥有 我试图使这个实现工作,当我尝试使用fn时,在我的b方法中得到类型错误和intelissense。所以基本上fn第一个参数是propOne的关键之一,而fn第二个参数是基于您选择的方法。因为在这个示例中,我选择了带有“methodOne”的fn,所以第二个参数被推断为number,因为methodOne的arg2是number类型 如果我为propOne方法编写类型,我就能够做到这一点,但我想知道是否有更好的方法来实现这一点 除了我认为稍后我们将讨论的bug之外,您可以让它大部分工作 第一个
如果我为propOne方法编写类型,我就能够做到这一点,但我想知道是否有更好的方法来实现这一点 除了我认为稍后我们将讨论的bug之外,您可以让它大部分工作 第一个问题是我们需要使用一个函数来帮助进行推理。简单变量的类型可以从初始化表达式推断出来,也可以在类型注释中指定,对于更复杂的行为,我们需要使用函数的推理行为 我们将使用两个类型参数,一个用于
propOne
,另一个用于propTwo
(我将其重命名为actions
和translations
,正如我们在推特上讨论的那样,最初的名称只是Vue商店道具的替代品)
捕获类型参数后,只需将操作的类型参数转换为函数的合适参数
const a = {
propOne: {
methodOne(arg1, arg2: number) {
console.info('hello...')
}
},
proptwo: {
b(fn, arg2) {
fn('methodOne', 'hello') // Error
fn('methodOne', 1) // OK
}
}
}
type Func=(…a:any[])=>void;
类型SkipFirstParameter=T扩展(a:any,…r:inferp)=>any?P:[];
类型操作=(突变:MK,…a:SkipFirstParameter)=>void
函数创建>(o:{
突变:M
行动:A
}) {
返回o
}
常数a=创建({
突变:{
方法一:(arg1:number,arg2:number)=>{
console.info('hello…'))
},
},
行动:{
b:(fn,arg2:数字)=>{
fn(“方法一”,arg2)
fn(“方法一”、“arg2”)
}
}
});
您会注意到我切换到了箭头函数,而不是简写语法或function
expression。这是因为arrow函数和其他函数之间的推理行为不同。我相信这是一个编译器错误和字段错误,但如果我们使用函数语法的方法,M
将被推断为unknown
。这可能与TS试图推断此类函数的方式有关,但行为上的差异可能是一个bug。嗨,提香,我更新了示例,使其更具体地针对实际问题。如果你愿意,我可以接受最初的回答,而不是问一个与当前问题不同的问题。让我知道
type Func = (...a: any[]) => void;
type SkipFirstParameter<T extends Func> = T extends (a: any, ... r: infer P) => any ? P : [];
type Actions<M extends Record<string, Func>> = <MK extends keyof M>(mutation: MK, ...a: SkipFirstParameter<M[MK]>) => void
function create<T, M extends Record<string, Func>, A extends Record<string, (f: Actions<M>, ...a: any[]) => void>>(o: {
mutations: M
actions: A
}) {
return o
}
const a = create({
mutations: {
methodOne: (arg1: number, arg2: number) => {
console.info('hello...')
},
},
actions: {
b: (fn, arg2: number) => {
fn("methodOne", arg2)
fn("methodOne", "arg2")
}
}
});