typescript 如何在记录值中正确键入泛型函数参数?

voj3qocg  于 2023-10-22  发布在  TypeScript
关注(0)|答案(1)|浏览(135)

在下一个例子中,getParamsKeyparams参数应该从其query字段中获得相同的类型,但它的类型为any

const getUser = async ({id}: {id: number}) => {}

const getUsers = async ({page = 1, pageSize = 5}) => {}

type QueryInfo<P> = {
  query: (params: P) => any
  getParamsKey: (params: P) => any
}

const addQueries = <T extends Record<keyof T, QueryInfo<any>>>(queries: T) => {}

addQueries({
  getUser: {
    query: getUser,
    getParamsKey: (params) => {}, // Here params is any, should be {id: number}
  },
  getUsers: {
    query: getUsers,
    getParamsKey: (params) => {}, // Here params is any, should be {page: number, pageSize: number}
  },
})

操场

bkhjykvo

bkhjykvo1#

对于这里的例子,你可以写addQueries()的调用签名,使得queriesgeneric类型参数T上的mapped type,目的是T可以从queries推断为一个对象类型,其值T[K]QueryInfo<>对应的类型参数:

const addQueries = <T extends object>(
  queries: { [K in keyof T]: QueryInfo<T[K]> }
) => { }

然后你的电话工作:

addQueries({
  getUser: {
    query: getUser,
    getParamsKey: (params) => params?.id ?? 0, 
    //             ^? (parameter) params: { id: number; }
  },
  getUsers: {
    query: getUsers,
    getParamsKey: (params) => params?.page ?? 0,
    //             ^? (parameter) params: { page?: number;  pageSize?: number; }
  },
})

类型参数T从参数的query属性推断为{ getUser: { id: number }; getUsers: { page?: number; pageSize?: number }},因此params回调参数的类型是正确的。
请注意,在上下文中推断回调参数类型的同时也推断对象中的泛型类型参数的 * 常规 * 问题尚未解决,并且可能永远无法解决。在这方面已经有了稳步的改善,但问题仍然存在。请参阅microsoft/TypeScript#47599了解一般问题,microsoft/TypeScript#53018了解与此处示例相似的代码的特定问题。最终,您所做的某些变化可能需要您手动注解回调参数,或者使用一些中间帮助函数。
Playground链接到代码

相关问题