Reputation: 11745
How can you generically construct a type derived from an object following the format below:
export const IMMEDIATE_FAMILY_MEMBERS_LIST_FIELDS = [
{ name: 'Relationship', type: 'dropdown', options: FAMILY_MEMBERS.NAMES },
{ name: 'Full name of family member as shown in passport', type: 'text' },
{
name: 'Country family member lives in',
type: 'dropdown',
options: COUNTRY.NAMES,
},
{
name: 'Immigration status in that country',
type: 'dropdown',
options: IMMIGRATION_STATUS_OPTIONS,
},
] as const
Into this:
export type ImmediateFamilyMembersListType = Array<{
Relationship: FamilyMembersType
'Full name of family member as shown in passport': string
'Country family member lives in': CountryType
'Immigration status in that country': keyof typeof IMMIGRATION_STATUS_OPTIONS
}>
Except without manually typing it every time for every object?
Here's my best attempt, but it's not generic nor does the A extends B ? string[] : string
even work:
type ImmediateFamilyMembersListFieldsType = typeof IMMEDIATE_FAMILY_MEMBERS_LIST_FIELDS
type ImmediateFamilyMembersListType = Record<ImmediateFamilyMembersListFieldsType[number]['name'], ImmediateFamilyMembersListFieldsType[number]['type'] extends 'dropdown' ? string[] : string>[]
Instead, it just resolves to:
type ImmediateFamilyMembersListType = Record<"Relationship" | "Full name of family member as shown in passport" | "Country family member lives in" | "Immigration status in that country", string>[]
Upvotes: 2
Views: 173
Reputation: 33111
Here you have util type:
enum FAMILY_MEMBERS {
NAMES = 'names'
}
enum COUNTRY {
NAMES = 'names'
}
enum IMMIGRATION_STATUS_OPTIONS { a = 'a' }
type Options = COUNTRY | IMMIGRATION_STATUS_OPTIONS | FAMILY_MEMBERS
type FamilyMembersType = {}
type CountryType = {}
export const IMMEDIATE_FAMILY_MEMBERS_LIST_FIELDS = [
{ name: 'Relationship', type: 'dropdown', options: FAMILY_MEMBERS.NAMES },
{ name: 'Full name of family member as shown in passport', type: 'text', options: '' },
{
name: 'Country family member lives in',
type: 'dropdown',
options: COUNTRY.NAMES,
},
{
name: 'Immigration status in that country',
type: 'dropdown',
options: IMMIGRATION_STATUS_OPTIONS,
},
] as const
export type ImmediateFamilyMembersListType = Array<{
Relationship: FamilyMembersType
'Full name of family member as shown in passport': string
'Country family member lives in': CountryType
'Immigration status in that country': keyof typeof IMMIGRATION_STATUS_OPTIONS
}>
type Values<T> = T[keyof T]
type Data = typeof IMMEDIATE_FAMILY_MEMBERS_LIST_FIELDS
type Elem = { readonly name: string; readonly type: string; readonly options: any }
type MapObject<El extends Elem> = {
[P in Values<Pick<El, 'name'>> & string]: El['options']
}
type Mapper<Arr extends ReadonlyArray<Elem>, Result extends Record<string, any> = {}> =
Arr extends []
? Result : Arr extends [infer H]
? H extends Elem
? Result & MapObject<H> : never : Arr extends readonly [infer H, ...infer Tail]
? Tail extends ReadonlyArray<Elem>
? H extends Elem
? Mapper<Tail, Result & MapObject<H>> : never : never : never
type Result = Mapper<Data>
I 've mocked some types because I don't know nothing about them.
I have used any
in few places, feel free to replace it with meaningful type.
Like I said, it is because I'm not aware about all constraints, but I believe that Mapper type should help you
Upvotes: 1