排除枚举但仍返回TypeScript中的枚举
为了在打字稿枚举中使用项目的子集,我们执行以下操作:
enum Operator {
EQUAL = 'EQUAL',
NOT_EQUAL = 'NOT_EQUAL',
LESS = 'LESS',
GREATER = 'GREATER',
}
type EqualOperators = Exclude<Operator, Operator.LESS | Operator.GREATER>
有什么办法可以让我EqualOperators成为一个enum而不是一个type,这样我就可以在脚本中使用它吗?
澄清一下,当我说“在脚本中使用它”时,我的意思是能够enum在 javascript 函数中使用值,而你不能使用它types,例如这样的:
enum Operator {
EQUAL = 'EQUAL',
NOT_EQUAL = 'NOT_EQUAL',
LESS = 'LESS',
GREATER = 'GREATER',
}
function getOperator() {
if (Operator.EQUAL) {
return "=";
}
if (Operator.NOT_EQUAL) {
return "!=";
}
throw new Error('invalid operator');
}
谢谢!
回答
如前所述,打字稿枚举既可以作为类型也可以作为对象。需要明确的是,所有类型和接口在运行时都消失了,但对象仍然存在。因此,换句话说,要有一个像if (op === Operator.EQUAL),的条件Operator必须在运行时存在(它确实存在,因为我们在这里使用枚举的“object-half”)。
在您的示例中,Operators“对象”将像这个对象一样:
{
EQUAL: 'EQUAL', // Operator.EQUAL
NOT_EQUAL: 'NOT_EQUAL', // Operator.NOT_EQUAL
LESS: 'LESS', // Operator.LESS
GREATER: 'GREATER', // Operator.GREATER
}
现在,当您使用 TypeScript 的类型系统从枚举派生新类型时,您所做的只是创建一个类型,但是要将 if 作为对象(如if条件中),您还需要实例化一个对象以配合它. 我想出了以下内容,它的好处是利用类型系统来确保在创建常量对象时不会遗漏任何内容(并确保只为每个“键”分配适当的值)。
type EqualOperators = Omit<typeof Operator, 'LESS' | 'GREATER'>;
const EqualOperators: EqualOperators = {
EQUAL: Operator.EQUAL,
NOT_EQUAL: Operator.NOT_EQUAL,
}
我定义EqualOperators为尽可能接近您的使用情况。我不确定某些要求是否会限制您采用这种方法,但如果不是,我个人的建议是改用Pick实用程序类型。IE:
type EqualOperators = Pick<typeof Operator, 'EQUAL' | 'NOT_EQUAL'>;
好处是你清楚地说明了什么是“相等”运算符,如果你添加新的运算符,你只需要记住EqualOperators当它们是相等运算符时更新类型,我觉得这是一个比记住更自然的思考过程EqualOperators当它们不是相等运算符时更新类型。但无论哪种方式都不理想,因为您不必记住更新另一个定义。所以关键是,当原始枚举的定义是以下之一时,使用我在这里建议的类型定义效果最好:
- 不会有太大变化,如果有的话(或者可能重命名元素)
- 只会通过将元素添加到“in”组来改变(这里的相等运算符)
- 只会通过将元素添加到“out”组来改变(不相等,例如更少,更大)