typescript 提取属性名称的安全方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33547583/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 06:49:04  来源:igfitidea点击:

Safe way to extract property names

typescriptreflectionmetaprogramming

提问by shadeglare

I'm looking for a way to get an object property name with typechecking that allows to catch possible regressions after refactoring.

我正在寻找一种通过类型检查获取对象属性名称的方法,该方法允许在重构后捕获可能的回归。

Here's an example: the component where I have to pass the property names as strings and it will be broken if I'll try to change the property names in the model.

这是一个示例:我必须将属性名称作为字符串传递的组件,如果我尝试更改模型中的属性名称,它将被破坏。

interface User {
   name: string;
   email: string;
}

class View extends React.Component<any, User> {

   constructor() {
      super();
      this.state = { name: "name", email: "email" };
   }

   private onChange = (e: React.FormEvent) => {
      let target = e.target as HTMLInputElement;
      this.state[target.id] = target.value;
      this.setState(this.state);
   }

   public render() {
      return (
         <form>
            <input
               id={"name"}
               value={this.state.name}
               onChange={this.onChange}/>
            <input
               id={"email"}
               value={this.state.email}
               onChange={this.onChange}/>
            <input type="submit" value="Send" />
         </form>
      );
   }
}

I'd appreciate if there's any nice solution to solve this issue.

如果有任何好的解决方案来解决这个问题,我将不胜感激。

回答by nzjoel

In TS 2.1 the keyof keyword was introduced which made this possible:

在 TS 2.1 中引入了 keyof 关键字,这使得这成为可能:

const propertyOf = <TObj>(name: keyof TObj) => name;

or

或者

const propertiesOf = <TObj>(_obj: (TObj | undefined) = undefined) => <T extends keyof TObj>(name: T): T => name;

These can then be used like this:

然后可以像这样使用它们:

propertyOf<MyInterface>("myProperty");

or

或者

const myInterfaceProperties = propertiesOf<MyInterface>();
myInterfaceProperties("myProperty");

or

或者

const myInterfaceProperties = propertiesOf(myObj);
myInterfaceProperties("myProperty");

This will give an error if myProperty is not a property of the type MyObj.

如果 myProperty 不是 MyObj 类型的属性,这将给出错误。

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html

回答by David Sherret

Right now there's not really a great way of doing this, but there are currently some open suggestions on github (See #1579, #394, and #1003).

现在并没有真正好的方法来做到这一点,但目前在 github 上有一些公开的建议(见#1579#394#1003)。

What you can do, is what's shown in this answer—wrap referencing the property in a function, convert the function to a string, then extract the property name out of the string.

您可以做的是此答案中显示的内容 - 在函数中引用属性,将函数转换为字符串,然后从字符串中提取属性名称。

Here's a function to do that:

这是一个函数来做到这一点:

function getPropertyName(propertyFunction: Function) {
    return /\.([^\.;]+);?\s*\}$/.exec(propertyFunction.toString())[1];
}

Then use it like so:

然后像这样使用它:

// nameProperty will hold "name"
const nameProperty = getPropertyName(() => this.state.name);

This might not work depending on how the code is minified so just watch out for that.

这可能不起作用,具体取决于代码的缩小方式,因此请注意这一点。

Update

更新

It's safer to do this at compile time. I wrote ts-nameofso this is possible:

在编译时这样做更安全。我写了ts-nameof所以这是可能的:

nameof<User>(s => s.name);

Compiles to:

编译为:

"name";

回答by theapache64

This is specifically for React/React-Native developers.

这是专门针对 React/React-Native 开发人员的。

To safely get property-name, I use the below class:

为了安全地获取属性名称,我使用以下类:

export class BaseComponent<P = {}, S = {}> extends Component<P, S> {
  protected getPropName = (name: keyof P) => name;
  protected getStateName = (name: keyof S) => name;
}

And replaced extends React.Component<PropTypes>with extends BaseComponnent<PropTypes,

并替换extends React.Component<PropTypes>extends BaseComponnent<PropTypes

Now, with in the Componentyou can call, this.getPropName('yourPropName')to get the property name.

现在,Component您可以通过调用this.getPropName('yourPropName')来获取属性名称。