Home > Mobile >  Extending a TypeScript interface with values from another object
Extending a TypeScript interface with values from another object

Time:12-22

I have the following interface:

export interface IFormField {
    /** Field name */
    name: string;

    /** Label to appear on form */
    label?: string;   // this is optional, since hidden fields do not have label

    /** Field type */
    type: 'accordion' | 'address' | 'camera' | 'category_box' | 'category_list';
}

and I'd like to extend the valid values of type picking them by an object like this one:

const arr = {
   'new_type1': 1,
   'new_type2': 2,
   'new_type3': 3,
};

How do I add new_type1, new_type2 and new_type3 to the list of valid names in the type field?

As a result, I'd like to have:

type: 'accordion' | 'address' | 'camera' | 'category_box' | 'category_list' | `new_type1` | `new_type2` | `new_type3`;

For another complete (not working) example:

const arr: any = {
   'new_type1': 1,
   'new_type2': 2,
   'new_type3': 3,
};

export interface IFormField {
    /** Field name */
    name: string;

    /** Label to appear on form */
    label?: string;   // this is optional, since hidden fields do not have label

    /** Field type */
    type: keyof typeof arr;
}

const f: IFormField = {
    name: 'ciao',
    type: "new_type1"
};

// adding a new key to `arr` at runtime
arr.type4 = 4;

const g: IFormField = {
    name: 'cioa',
    type: 'type4'  // <- valid for IFormField.type ?
}

Is it possible?

Thanks

CodePudding user response:

It is easy to construct the desired type:

  • capture the new keys in type NewFieldTypes
  • make an union of old types and new types
  • lastly, substitute the type field in IFormField
export interface IFormField {
    /** Field name */
    name: string;

    /** Label to appear on form */
    label?: string;   // this is optional, since hidden fields do not have label

    /** Field type */
    type: 'accordion' | 'address' | 'camera' | 'category_box' | 'category_list';
}

const arr = {
   'new_type1': 1,
   'new_type2': 2,
   'new_type3': 3,
};

type NewFieldTypes = keyof typeof arr;
type ExpandedFieldTypes = IFormField['type'] | NewFieldTypes

type ExpandedIFormField = Omit<IFormField, "type"> & {
  type: ExpandedFieldTypes
};

Playground

CodePudding user response:

type MyCombinedUnion = keyof typeof arr | IFormField["type"]

https://www.typescriptlang.org/play?ts=4.3.5&ssl=19&ssc=6&pln=19&pc=21#code/FAUwHgDg9gTgLgAgJYDs4hgMwIYGMQICSAYrALbFIgA2AJggN7AIsID0AVBwpTfStjIEObZqwFCAXAgDOcGKgDmAbmBiWnbgBlsAIxoI4UBNggQQ2GAigoEmcghHqE1PTQD80uQpQrWbNkMACyQZZDCoCDgkG2xqABpZVHwEENpaEFtMKjow2mMUKEQg7AA3Ald9ajVWdi4eHPo4AE9zR1FalvNpAHI8XFhaGJQehAAfBD70mBAZGVGJntxBDGwFyeX0RVhmgH1dKDB1pewtnd3qULge1QBfNQGUORMYKwBeRnUelBAAd12uiAAIw9aRA JfH7-QEAJlBCBhENY3z ANaIAAzPCMRDbqpgICEABZZoAYSgZF0qBAtAAqihhggPgBrEDNKCYQzojkvKwTEjkXh0ADaACJAaKALpAA

  • Related