打字稿:带有枚举的通用函数
Typescript: Generic function with enums
我正在使用多个枚举作为全局参数。
enum color {
'red' = 'red',
'green' = 'green',
'blue' = 'blue',
};
enum coverage {
'none' = 'none',
'text' = 'text',
'background' = 'background',
};
我将所有枚举合并到一个类型 myEnums
。
type myEnums = color | coverage;
现在我想检查和访问枚举的值。例如:
// Returns undefined if the argument value is not a color.
function getColor(value: string): color | undefined{
if(value in color) return value as color;
return undefined;
}
因为有几个枚举,我想创建一个通用函数来访问我的所有枚举。我尝试了以下方法:
function getParam<T extends myEnums>(value: string): T | undefined {
if(value in T) return value as T;
return undefined;
}
getParam<color>('red', color); // => should return 'red'
getParam<coverage>('test', coverage); // => should return undefined
但是 Typescript 编译器说:
'T' 仅指类型,但在这里用作值。'.
所以我向函数添加了一个参数 list: T
,但是 Typescript 假设参数 list
的类型为 string
(而不是 object
)。
'in' 表达式的右侧不能是原语。
function getParam<T extends allEnums>(value: string, list: T): T | undefined {
if(value in list) return value as T;
return undefined;
}
那么如何使用 T
作为枚举来调用通用函数?
我认为关键是 T
的正确输入,你必须告诉 TS,T 是“类似枚举定义”的对象。我四处寻找,发现这个,或多或少工作
我的一个项目中有这样的东西:
export function parseEnum<E, K extends string>(
enumDef: { [key in K]: E },
str: string | undefined
): E | undefined {
if (str && str in enumDef) {
return enumDef[str as K] as E;
}
return undefined;
}
所以,这就是“普通枚举”的作用,而您想使用它来对枚举进行“求和”。
幸运的是,由于枚举在 JS&TS 中的实现方式,您可以像这样合并枚举定义对象:
const myEnums = {...coverage, ...color }
// typeof myEnums = coverage | color;
有效:
const x = parseEnum(myEnums, 'x');
// typeof x = coverage | color | undefined;
打字稿游乐场here
enum
是TypeScript中的一种特殊数据结构。
如果您想对泛型进行限制,则需要使用 typeof Enum
。
在您的示例中,您期望 typeof color | typeof coverage
而不是 color|coverage
。
因为最后一个是值的联合无论第一个是枚举的联合。
C考虑这个例子:
enum color {
'red' = 'red',
'green' = 'green',
'blue' = 'blue',
};
enum coverage {
'none' = 'none',
'text' = 'text',
'background' = 'background',
};
type myEnums = color | coverage;
const hasProperty = <Obj, Prop extends PropertyKey>(obj: Obj, prop: Prop)
: obj is Obj & Record<Prop, unknown> =>
Object.prototype.hasOwnProperty.call(obj, prop);
function getParam<Keys extends PropertyKey, Value, E extends Record<Keys, Value>, Key extends keyof E>(enm: E, key: Key): E[Key]
function getParam<Keys extends PropertyKey, Value, E extends Record<Keys, Value>, Key extends PropertyKey>(enm: E, key: Key): Value | undefined
function getParam<E extends typeof color | typeof coverage, Key extends keyof E>(enm: E, key: Key): E[Key]
function getParam<E extends typeof color | typeof coverage, Key extends string>(enm: E, key: Key): undefined | E
function getParam<E extends typeof color | typeof coverage | Record<string, unknown>, Key extends keyof E>(enm: E, key: Key): E[Key] | undefined {
return hasProperty(enm, key) ? enm[key] : undefined
}
const y = getParam(color, 'red'); // => color.red
const x = getParam(coverage, 'undefined'); // => undefined
const x2 = getParam({}, 'undefined'); // => unknown
const higherOrder = (key: string) => getParam(color, key)
const z = higherOrder('red') // typeof color | undefined
请记住,我不确定你想如何处理高阶函数,所以我在最后一个例子中返回了 enum
和 undefined
的联合
至于这一行 if(value in T)
:T
是一种类型,您不能将其视为运行时值。
我正在使用多个枚举作为全局参数。
enum color {
'red' = 'red',
'green' = 'green',
'blue' = 'blue',
};
enum coverage {
'none' = 'none',
'text' = 'text',
'background' = 'background',
};
我将所有枚举合并到一个类型 myEnums
。
type myEnums = color | coverage;
现在我想检查和访问枚举的值。例如:
// Returns undefined if the argument value is not a color.
function getColor(value: string): color | undefined{
if(value in color) return value as color;
return undefined;
}
因为有几个枚举,我想创建一个通用函数来访问我的所有枚举。我尝试了以下方法:
function getParam<T extends myEnums>(value: string): T | undefined {
if(value in T) return value as T;
return undefined;
}
getParam<color>('red', color); // => should return 'red'
getParam<coverage>('test', coverage); // => should return undefined
但是 Typescript 编译器说: 'T' 仅指类型,但在这里用作值。'.
所以我向函数添加了一个参数 list: T
,但是 Typescript 假设参数 list
的类型为 string
(而不是 object
)。
'in' 表达式的右侧不能是原语。
function getParam<T extends allEnums>(value: string, list: T): T | undefined {
if(value in list) return value as T;
return undefined;
}
那么如何使用 T
作为枚举来调用通用函数?
我认为关键是 T
的正确输入,你必须告诉 TS,T 是“类似枚举定义”的对象。我四处寻找,发现这个,或多或少工作
我的一个项目中有这样的东西:
export function parseEnum<E, K extends string>(
enumDef: { [key in K]: E },
str: string | undefined
): E | undefined {
if (str && str in enumDef) {
return enumDef[str as K] as E;
}
return undefined;
}
所以,这就是“普通枚举”的作用,而您想使用它来对枚举进行“求和”。
幸运的是,由于枚举在 JS&TS 中的实现方式,您可以像这样合并枚举定义对象:
const myEnums = {...coverage, ...color }
// typeof myEnums = coverage | color;
有效:
const x = parseEnum(myEnums, 'x');
// typeof x = coverage | color | undefined;
打字稿游乐场here
enum
是TypeScript中的一种特殊数据结构。
如果您想对泛型进行限制,则需要使用 typeof Enum
。
在您的示例中,您期望 typeof color | typeof coverage
而不是 color|coverage
。
因为最后一个是值的联合无论第一个是枚举的联合。
C考虑这个例子:
enum color {
'red' = 'red',
'green' = 'green',
'blue' = 'blue',
};
enum coverage {
'none' = 'none',
'text' = 'text',
'background' = 'background',
};
type myEnums = color | coverage;
const hasProperty = <Obj, Prop extends PropertyKey>(obj: Obj, prop: Prop)
: obj is Obj & Record<Prop, unknown> =>
Object.prototype.hasOwnProperty.call(obj, prop);
function getParam<Keys extends PropertyKey, Value, E extends Record<Keys, Value>, Key extends keyof E>(enm: E, key: Key): E[Key]
function getParam<Keys extends PropertyKey, Value, E extends Record<Keys, Value>, Key extends PropertyKey>(enm: E, key: Key): Value | undefined
function getParam<E extends typeof color | typeof coverage, Key extends keyof E>(enm: E, key: Key): E[Key]
function getParam<E extends typeof color | typeof coverage, Key extends string>(enm: E, key: Key): undefined | E
function getParam<E extends typeof color | typeof coverage | Record<string, unknown>, Key extends keyof E>(enm: E, key: Key): E[Key] | undefined {
return hasProperty(enm, key) ? enm[key] : undefined
}
const y = getParam(color, 'red'); // => color.red
const x = getParam(coverage, 'undefined'); // => undefined
const x2 = getParam({}, 'undefined'); // => unknown
const higherOrder = (key: string) => getParam(color, key)
const z = higherOrder('red') // typeof color | undefined
请记住,我不确定你想如何处理高阶函数,所以我在最后一个例子中返回了 enum
和 undefined
的联合
至于这一行 if(value in T)
:T
是一种类型,您不能将其视为运行时值。