export type ReadPayloadT<T extends keyof ERPTypes> = {
model: T
ids: number[]
fields?: (keyof ERPTypes[T])[]
with_context?: string
with_company?: number
}
export const readQuery = async <T extends keyof ERPTypes>(
payload: ReadPayloadT<T>
): Promise<
ReadPayloadT<T> extends { fields: (keyof ERPTypes[T])[] }
? Pick<ERPTypes[T], keyof ERPTypes[T]>[]
: ERPTypes[T][]
> => {
if (!token) {
let { data } = await auth()
token = data.access_token
}
return axios
.post(process.env['E_URL'] + '/api/v2/read', payload, {
headers: {
DATABASE: process.env['E_DB']!,
Authorization: 'Bearer ' + token,
},
})
.then((res) => res.data)
}
readQuery({
ids: [234],
model: 'res.company',
fields: ['vat'],
}).then((res) => {
res[0].vat_check_vies
})
I have this function "readQuery"
The return type should be ERPTypes[T]
If i provide fields
then the return type should only contain the type of the keys i provided inside fields
In this case res[0]
should only contain res[0].vat
and nothing else.
If i dont provide fields
then res[0] should provide every key of ERPTypes[T]
So basically, the backend returns me the object with only the propertys of fields
. If i provide nothing then it returns me the whole object.
I was thinking about overloads, but i want to ask if there is a better idea?
How do i do this?
EDIT:
export type ReadPayloadWithFieldsT<T extends keyof ERPTypes> = {
model: T
ids: number[]
fields: (keyof ERPTypes[T])[]
with_context?: string
with_company?: number
}
export type ReadPayloadWithoutFieldsT<T extends keyof ERPTypes> = {
model: T
ids: number[]
with_context?: string
with_company?: number
}
export type ReadQueryOverloadT = {
<T extends keyof ERPTypes>(payload: ReadPayloadWithFieldsT<T>): Promise<
Pick<ERPTypes[T], keyof ERPTypes[T]>
>
<T extends keyof ERPTypes>(payload: ReadPayloadWithoutFieldsT<T>): Promise<
ERPTypes[T][]
>
}
export const readQuery: ReadQueryOverloadT = async (payload) => {
if (!token) {
let { data } = await auth()
token = data.access_token
}
return axios
.post(process.env['E_URL'] + '/api/v2/read', payload, {
headers: {
DATABASE: process.env['E_DB']!,
Authorization: 'Bearer ' + token,
},
})
.then((res) => res.data)
}
readQuery({
ids: [234],
model: 'res.company',
}).then((res) => {
res[0]
})
I have made it so far.
My problem is now, how do i pick those keys i used in fields
?
Pick<ERPTypes[T], keyof ERPTypes[T]>
With this solution it picks nothing.
In this example it should only pick vat
because i wrote it.
2
Answers
I have a solution!
One way is to use conditional types in the return type of your function, such as
Promise<ReadPayloadT<T> extends { fields: (keyof ERPTypes[T])[] } ? Pick<ERPTypes[T], keyof ERPTypes[T]>[] : ERPTypes[T][]>.
However, this might require you to use type assertions in your function body, such as return axios.post(…) as any.Another way is to use overloads instead of conditional types. You can define multiple function signatures for different parameter types and return types, such as: