0

Given the interface

interface FormField {
    name: string;
}

and a value such as:

const fields: FormField[] = [
    { name: 'givenName' },
    { name: 'familyName' }
]

I would like to infer this interface:

interface FormModel {
    givenName: string;
    familyName: string;
}

So use the array's property values as property names.

I tried something like:

type Model<T extends Array<FormField>> = { [K['name'] in T]: string };

but this doesn't work. Is this kind of thing possible in Typescript?

1 Answer 1

1

Your solution already goes in the right direction, we can tune the types a bit up to make it work:

// make name generic, so we can refer to concrete string literal
interface FormField<T extends string> {
    name: T;
}

const fields = [
    { name: 'givenName' },
    { name: 'familyName' }
] as const  // const assertion to retain strings "givenName" and "familyName"

// T[number] gives all possible array values, T[number]["name"] all possible names
type Model<T extends ReadonlyArray<FormField<any>>> = { [K in T[number]["name"]]: string };

type FormModel = Model<typeof fields> // { givenName: string; familyName: string; }

fields doesn't have an explicit type FormField[] anymore in order to preserve literal types. If you still want to have stong type checks for fields, you can use a factory function:

const formField = <T extends string>(t: T): FormField<T> => ({ name: t })

const fields = [
  formField('givenName'),
  formField('familyName'),
  formField(3) // 💣, error
]

Code sample

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.