我正在寻找一种方法来获取带有类型检查的对象属性名称,以便在重构后捕获可能的回归。
这是一个例子:我必须将属性名称作为字符串传递的组件,如果我将尝试更改模型中的属性名称,它将被破坏。
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>
);
}
}
如果有任何解决此问题的解决方案,我会很感激。
答案 0 :(得分:25)
在TS 2.1中引入了keyof关键字,使其成为可能:
const propertyOf = <TObj>(name: keyof TObj) => name;
或
const propertyNamesOf = <TObj>(obj: TObj = null) => (name: keyof TObj) => name;
然后可以这样使用:
propertyOf<MyInterface>("myProperty");
或
const myInterfaceProperties = propertyNamesOf<MyInterface>();
myInterfaceProperties("myProperty");
或
const myInterfaceProperties = propertyNamesOf(myObj);
myInterfaceProperties("myProperty");
如果myProperty不是MyObj类型的属性,则会出错。
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html
答案 1 :(得分:22)
目前还没有一种很好的方法可以做到这一点,但目前github上有一些公开的建议(见#1579,#394和#1003)。
你可以做什么,是this answer中显示的内容 - 在函数中引用属性,将函数转换为字符串,然后从字符串中提取属性名称。
这是一个执行此操作的功能:
function getPropertyName(propertyFunction: Function) {
return /\.([^\.;]+);?\s*\}$/.exec(propertyFunction.toString())[1];
}
然后像这样使用它:
// nameProperty will hold "name"
const nameProperty = getPropertyName(() => this.state.name);
这可能不起作用,具体取决于代码的缩小方式,因此请注意这一点。
<强>更新强>
在编译时这样做更安全。我写了ts-nameof所以这是可能的:
nameof<User>(s => s.name);
编译为:
"name";
答案 2 :(得分:2)
这是专门针对React / React-Native开发人员的。
为了安全地获取属性名称,我使用以下类:
export class BaseComponent<P = {}, S = {}> extends Component<P, S> {
protected getPropName = (name: keyof P) => name;
protected getStateName = (name: keyof S) => name;
}
然后将extends React.Component<PropTypes>
替换为extends BaseComponnent<PropTypes
,
现在,在Component
中,您可以调用this.getPropName('yourPropName')
来获取属性名称。