简体   繁体   English

TypeScript:在编译时使用枚举作为接口/对象键的过滤器

[英]TypeScript: Use Enum as filter for Interface/Object keys in Compile Time

Question

I have an enum (string to string) that contains valid keys for a function .我有一个enum (字符串到字符串),其中包含一个function有效键。 I also have an object (or interface ) that has some keys in the enum, and some not.我还有一个object (或interface ),它在枚举中有一些键,有些没有。

How can I set the parameter of my function to only be only the keys from the interface that exist in the enum ?如何将函数的参数设置为仅来自enum中存在的interface的键 (eg Pick, Extract, Intersection, whatever you wanna call them, that properly preserves the keys.) (例如 Pick、Extract、Intersection,无论您想怎么称呼它们,都可以正确保留密钥。)

Example例子

The following example is irrelevant to my project, but proper exhibits my need.以下示例与我的项目无关,但适当地展示了我的需要。

Let's say the enum and the interface are as following:假设enuminterface如下:

enum PromotableProperties {
  SALARY = "salary",
  SIGNON_BONUS = "signonBonus",
  ANNUAL_BONUS = "annualBonus",
}

interface IExistingEmployee {
  id:           number;
  name:         string;
  salary:       number;
  signonBonus:  number;
  age:          number;
}

Now the actual code is:现在实际的代码是:

type ValidPropsOf<ENUM_T, OBJ_T> = ...; // I want this!

type PromotablePropsForExistingEmployee = ValidPropsOf<PromotableProperties, IExistingEmployee>;


function promoteEmployeeBy(
  emp: IExistingEmployee,
  prop: ValidPropsOf<PromotableProperties, IExistingEmployee>,
  byValue: number,
): void {
  emp[prop] += byValue;
  console.log(`${emp.name}'s ${prop} is increase by ${byValue}'`);
}

const goodOldJohn: IExistingEmployee = {
  id: 5,
  name: "john",
  salary: 20000,
  signonBonus: 1000,
  age: 25,
};

promoteEmployeeBy(goodOldJohn, PromotableProperties.SALARY, 100);
promoteEmployeeBy(goodOldJohn, PromotableProperties.ANNUAL_BONUS, 100); // Error
promoteEmployeeBy(goodOldJohn, "age", 100); // Error

Note that the second function call should fail, because ANNUAL_BONUS doesn't exist in the IExistingEmployee , and the third call should fail because age is not in PromotableProperties .注意,第二个函数调用失败,因为ANNUAL_BONUS不在存在IExistingEmployee和第三个电话应该失败,因为agePromotableProperties

What I need我需要的

... is the utility type of type ValidPropsOf<ENUM_T, OBJ_T> = ... the returns the keys that exist in both the enum (as value) and the object/interface. ... 是type ValidPropsOf<ENUM_T, OBJ_T> = ...的实用程序类型,返回存在于枚举(作为值)和对象/接口中的键。

TS Playground TS游乐场

here . 在这里

What didn't work什么没用

I assumed Extract (from the TS official Utility Types ) should work, but I couldn't get it to work.我认为Extract (来自TS 官方实用程序类型)应该可以工作,但我无法让它工作。

I also tried Pick and a bunch of other utility types from the two known TS Utility repos, I knew of, but none helped.我还尝试了Pick和我知道的两个已知 TS Utility 存储库中的许多其他实用程序类型,但都没有帮助。

  1. https://github.com/piotrwitek/utility-types https://github.com/piotrwitek/utility-types
  2. https://github.com/krzkaczor/ts-essentials https://github.com/krzkaczor/ts-essentials

What did work什么起作用了

What did work for me was a double Exclude !对我Exclude是双重Exclude It was:它是:

type ValidPropsOf<ENUM_T, OBJ_T> = Exclude<ENUM_T, Exclude<ENUM_T, keyof OBJ_T>>;

Apparently Exclude preserves the keys properly (and doesn't aggressively generalize individual keys).显然Exclude正确地保留了密钥(并且不会积极地概括单个密钥)。 So From the enum I take out the ones that don't exist in the object (call them badProps ), and the the good ones would be goodProps = allProps - badProps .所以从enum我取出object不存在的那些(称它们为badProps ),好的将是goodProps = allProps - badProps

It completely preserved the individual keys.它完全保留了单个密钥。 You can test it by hovering over the type in the function in this working TS Playground Link .您可以通过将鼠标悬停在此工作 TS Playground Link 中函数中的类型上来测试它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM