typescript - Hur man korrekt typiserar generiska funktioner i postvärden?
I nästa exempel har params-argumentet till getParamsKey korrekt typ, hämtad från query-fältet, men resultatet i mergeResults har typen any.
Förväntat resultat: både argumenten och resultatet är korrekt typade.
type User = {id: number}
const getUser = async ({id}: {id: number}): Promise<User> => ({
id,
})
const getUsers = async ({page = 1, pageSize = 5}): Promise<User[]> => []
type QueryInfo<P, R> = {
query: (params: P) => Promise<R>
mergeResults: (oldResult: R, newResult: R, params: P) => R
}
const makeQueries = <T extends object>(queries: {[K in keyof T]: QueryInfo<T[K], any>}) => queries
const queries = makeQueries({
getUsers: {
query: getUsers,
// PROBLEM results has type `any`, params are properly typed
mergeResults: (oldResult, newResult, params) => newResult,
},
getUser: {
query: getUser,
// PROBLEM results has type `any`, params are properly typed
mergeResults: (oldResult, newResult, params) => newResult,
},
})
// PROBLEM queries results have `any` type
queries.getUser.query
queries.getUsers.query
Lekplats
Svar #1
En av lösningarna
type User = {id: number}
const getUser = async ({id}: {id: number}): Promise<User> => ({
id,
})
const getUsers = async ({page = 1, pageSize = 5}): Promise<User[]> => []
type QueryInfo<P, R> = {
query: (params: P) => Promise<R>
mergeResults: (oldResult: R, newResult: R, params: P) => R
}
const makeQueries = <T, Q>(queries: {[K in keyof (T&Q)]: K extends (keyof (T | Q)) ? QueryInfo<T[K], Q[K]> : never}) => queries
const queries = makeQueries({
getUsers: {
query: getUsers,
mergeResults: (oldResult, newResult, params) => newResult,
},
getUser: {
query: getUser,
mergeResults: (oldResult, newResult, params) => newResult,
},
})
queries.getUser.query
queries.getUsers.query
Lekplats
Svar #2
Förutom att använda en separat hjälpfunktion makeQuery som hjälper till att härleda det inre objektet tror jag inte att det är möjligt (eller det är möjligt men du kommer att stöta på vissa begränsningar som att ReturnType inte kommer att härledas)
Hjälpfunktionen makeQuery kommer att hjälpa dig att koppla query och mergeResults så att returtypen också kommer att användas:
const makeQuery = <P, R>(query: QueryInfo<P, R>) => query;
TypeScript Playground - https://tsplay.dev/NDVD4W
