How to create a new Type from an existing Type and with dynamic keys in TypeScript

I have created a defined Type in TypeScript, but I want to create a new with new fields, or dynamic fields.

Is this possible? The answer is yes!

Let’s get started on how to!

Here’s an existing type:


type LifeStyles =
    {
        type: 'active'
    }
    | {
        type: 'healthy'
    }
    | {
        type: 'Solo'
    }
    | {
        type: 'nomadic'
    }

const result: LifeStyles = {
    type: 'active'
}

The code above is an example of what an object can look like. We have multiple lifestyles, and now I want to create a new type that allows dynamic Id’s according to the type.

The first step is to create a new Type in TypeScript:


type LifeStyleWithId = {
    [LifeStylesType in LifeStyles['type']]: {}
}

What the code above does so far is, it’s transforming a union to another union by using the in operator as a for-loop.

So far the, the type is transformed to look like this:


const result: LifeStyleWithId = {
    active: {},
    healthy: {},
    Solo: {},
    nomadic: {},
}

The goal is to keep the type field and add a new dynamic field ${type}Id. The new field will be a dynamic field, depending on the type.


type LifeStyleWithId = {
    [LifeStylesType in LifeStyles['type']]: {
        type: LifeStylesType
    }
}[LifeStyles['type']]

The code above now turns LifeStyleWithId into a union, which it creates objects into with these possible outputs:


type LifeStyleWithId = {
    type: "active";
} | {
    type: "healthy";
} | {
    type: "Solo";
} | {
    type: "nomadic";
}

Now let’s create dynamic a key field inside the type LifeStyleWithId. To help us accomplish this, we’re going to use the Record and string interpolation to help us create dynamic fields.


type LifeStyleWithId = {
    [LifeStylesType in LifeStyles['type']]: {
        type: LifeStylesType
    } & Record<`${LifeStylesType}Id`,string>
}[LifeStyles['type']]

That’s it! Now you can have these potential outcomes when assigning a variable with a type LifeStyleWithId.


const a: LifeStyleWithId = {
    type: 'active',
    activeId: '12312'
}

const b: LifeStyleWithId = {
    type: 'healthy',
    healthyId: '12312'
}

const c: LifeStyleWithId = {
    type: 'nomadic',
    nomadicId: '12312'
}

const d: LifeStyleWithId = {
    type: 'Solo',
    SoloId: '12312'
}

I like to tweet about TypeScript and post helpful code snippets. Follow me there if you would like some too!