I'm looking for a way to infer type for each and every spread argument of my type function.
Let's say I have the two fields with the following definition.
type Field<T> = { value: T, name: string }
const field1 = { value: 12, name: 'age' }
const field2 = { value: 'foo', name: 'nickname' }
and I want to be able to pass these fields as my spread arguments to the following function, that would be called in a following fashion
useForm('registration', field1, field2)
So I tried using a conditional type inferrence as per the official docs, which did solve the issue for the most part
type InferredFields<T> = T extends { value: infer V }[]
? Record<string, Field<V>>
: never
const useForm = <T extends Field<unknown>[]>(name: string, ...args: T) => {
const fields: InferredFields<T> = args.reduce(
(res, field) => ({
...res,
[field.name]: field.value,
}),
{} as InferredFields<T>,
)
return {
name,
fields
}
}
const form = useForm('bar', field1, field2)
My only issue is, it cannot properly discriminate the union produced by the inferred value of the passed array generic based on which value we are using.
type FieldValue<T> = T extends { value: infer V } ? V : never
// This is an issue since the return type of form is
// { fields: Record<string, string | number> }
// instead of the properly inferred value type
const v1: FieldValue<typeof field1> = form.fields['age'].value // error
const v2: FieldValue<typeof field2> = form.fields['nickname'].value // error
Any idea how can i properly map the value types for each Field
type passed as an argument?