TS:如何使用字符串创建类型工厂来生成键
TS : How to create a type factory using a string to generate the keys
我正在尝试创建一种方法来轻松生成一种类型,该类型定义了与键中特定名称模式关联的大量键值。
我有一个非常重复的特定类型,对于任何指标(用于分析),我有 4 个相关联的键。
例如,对于 firstPageVisible
指标,我将有 firstPageVisibleMetrics
、firstPageVisibleCount
、firstPageVisibleMetricsPerDevices
、firstPageVisibleCountPerDevices
。
但是由于我有很多指标,我希望有某种工厂可以使它更易于阅读。
我在想象这样的事情:
type DetailedMetric<Type> = (
name: string,
) => {
[`${name}Metrics`]?: Type;
[`${name}Count`]?: number;
[`${name}MetricsPerDevices`]?: PerDeviceData<Type>;
[`${name}CountPerDevices`]?: PerDeviceData<number>;
};
但我遇到了错误:A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.
。
而且我找不到令人满意的解决方法。
最后,我想要看起来像这样(或类似)的东西:
type StoryDataType = {
_id: string;
...;
} & DetailedMetric("firstPageVisible")<number> &
DetailedMetric("metric2")<number> &
DetailedMetric("metric3")<number> &
DetailedMetric("metric4")<number> &
...;
您可以这样定义 DetailedMetrics
:
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>
}
您可以映射到一个基本类型上,并使用称为 Key Remapping 的相对较新的 TypeScript 功能,允许您在尝试执行操作时计算 属性 键。
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];
};
通过这种方式,您可以在我们的 Base
类型中定义新属性并自动继承它们。
我正在尝试创建一种方法来轻松生成一种类型,该类型定义了与键中特定名称模式关联的大量键值。
我有一个非常重复的特定类型,对于任何指标(用于分析),我有 4 个相关联的键。
例如,对于 firstPageVisible
指标,我将有 firstPageVisibleMetrics
、firstPageVisibleCount
、firstPageVisibleMetricsPerDevices
、firstPageVisibleCountPerDevices
。
但是由于我有很多指标,我希望有某种工厂可以使它更易于阅读。
我在想象这样的事情:
type DetailedMetric<Type> = (
name: string,
) => {
[`${name}Metrics`]?: Type;
[`${name}Count`]?: number;
[`${name}MetricsPerDevices`]?: PerDeviceData<Type>;
[`${name}CountPerDevices`]?: PerDeviceData<number>;
};
但我遇到了错误:A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.
。
而且我找不到令人满意的解决方法。
最后,我想要看起来像这样(或类似)的东西:
type StoryDataType = {
_id: string;
...;
} & DetailedMetric("firstPageVisible")<number> &
DetailedMetric("metric2")<number> &
DetailedMetric("metric3")<number> &
DetailedMetric("metric4")<number> &
...;
您可以这样定义 DetailedMetrics
:
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>
}
您可以映射到一个基本类型上,并使用称为 Key Remapping 的相对较新的 TypeScript 功能,允许您在尝试执行操作时计算 属性 键。
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];
};
通过这种方式,您可以在我们的 Base
类型中定义新属性并自动继承它们。