Search code examples
typescripttypescript-generics

TS : How to create a type factory using a string to generate the keys


I am trying to create a way to easily generate a type that defines a multitude of key values association with a specific name pattern in the keys.

I have a specific type that is very repetitive, as for any metrics (working on analytics), I have a 4 keys associated.

For example, for the firstPageVisible metric, I will have firstPageVisibleMetrics, firstPageVisibleCount, firstPageVisibleMetricsPerDevices, firstPageVisibleCountPerDevices.

But as I have many metrics, I would like to have some sort of factory to make is easier to read.

I was imagining something like :

type DetailedMetric<Type> = (
    name: string,
) => {
    [`${name}Metrics`]?: Type;
    [`${name}Count`]?: number;
    [`${name}MetricsPerDevices`]?: PerDeviceData<Type>;
    [`${name}CountPerDevices`]?: PerDeviceData<number>;
};

But I am having the error : A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type..

And I cannot find a satisfying way to resolve this.

In the end, I would like to have something that looks like this (or similar) :


type StoryDataType = {
    _id: string;
    ...;
} & DetailedMetric("firstPageVisible")<number> &
    DetailedMetric("metric2")<number> &
    DetailedMetric("metric3")<number> &
    DetailedMetric("metric4")<number> &
    ...;

Solution

  • You can define DetailedMetrics like this:

    type DetailedMetric<Type, Name extends string> =  {
        [K in `${Name}Metrics`]?: Type 
    } & {
        [K in `${Name}Count`]?: number 
    } & {
        [K in `${Name}MetricsPerDevices`]?: PerDeviceData<Type> 
    } & {
        [K in `${Name}CountPerDevices`]?: PerDeviceData<number> 
    }
    

    Playground