'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 1:[1]
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>
}
Solution 2:[2]
You could map over a base type and use a relatively new TypeScript feature called Key Remapping allowing you to compute a property key as you are trying to do`.
type Base<T> = {
Metrics?: T;
Count?: number;
MetricsPerDevices?: number;
CountPerDevices?: number;
}
type DetailedMetric<Type> = <N extends string>(
name: N,
) => {
// Remap the name to be our generic `N`.
[Key in keyof Base<Type> as `${N}${Key}`]: Base<Type>[Key];
};
This way you can define new properties in our Base type and have them automatically carried over.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Tobias S. |
| Solution 2 | alistair |
