Home > Software design >  Typescript extract type of nested object in template type
Typescript extract type of nested object in template type

Time:01-03

I have the following type:

type field_<T> =
    {
        value: T;
        error:
            {
                error: boolean;
                message: string;
            }
        visited: boolean;
        validate: (value: T) => boolean;
    }

and a form that contains all the fields:

interface form_model_
{
    firstName: field_<string>;
    lastName: field_<string>;
}

etc..

I would like to collect all the value fields in a way similar to:

type value_type<form_model_interface_> = {
    [key_ in keyof form_model_interface_]: ?*?;
}

what would replace the ?*? or is there a better way to go about it?

CodePudding user response:

There is two options.

First one with conditional types:

type field_<T> =
    {
        value: T;
        error:
        {
            error: boolean;
            message: string;
        }
        visited: boolean;
        validate: (value: T) => boolean;
    }

interface form_model_ {
    firstName: field_<string>;
    lastName: field_<string>;
}

type value_type<form_model_interface_> = {
    [key_ in keyof form_model_interface_]: form_model_interface_[key_] extends field_<any> ? form_model_interface_[key_]['value'] : never
}

// type Result = {
//     firstName: string;
//     lastName: string;
// }
type Result = value_type<form_model_>

Playground

Second one with appropriate constraint for form_model_interface_ generic in value_type. Please keep in mind that in this case you need to define form_model_ as a type instead of interface because type is indexed by default

type field_<T> =
    {
        value: T;
        error:
        {
            error: boolean;
            message: string;
        }
        visited: boolean;
        validate: (value: T) => boolean;
    }

type form_model_ = {
    firstName: field_<string>;
    lastName: field_<string>;
}

type value_type<form_model_interface_ extends Record<string, field_<any>>> = {
    [key_ in keyof form_model_interface_]: form_model_interface_[key_]['value']
}

// type Result = {
//     firstName: string;
//     lastName: string;
// }
type Result = value_type<form_model_>

Playground

Be aware, that there is naming convention in typescript. All types should be Capitalized and CamelCased. So field_ should be written as Field.

  • Related