Un moyen sécurisé d'extraire les noms de propriétés dans TypeScript

Je cherche un moyen d'obtenir un nom de propriété d'objet avec une vérification de détection qui permet d'attraper des régressions possibles après la refactorisation.

Voici un exemple: le composant où je dois passer les noms de propriété en tant que chaînes et il sera brisé si j'essaierai de modifier les noms de propriétés dans le modèle.

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> ); } } 

J'apprécierais s'il y a une solution agréable pour résoudre ce problème.

Dans TS 2.1, la clé du mot-clé a été introduite, ce qui a permis:

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

ou

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

Ceux-ci peuvent alors être utilisés comme ceci:

 propertyOf<MyObj>("myProperty"); 

ou

 const myObjProperties = propertyNamesOf<MyObj>(); myObjProperties("myProperty"); 

Cela donnera une erreur si myProperty n'est pas une propriété du type MyObj.

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

À l'heure actuelle, il n'y a pas vraiment une excellente façon de le faire, mais il existe actuellement des suggestions ouvertes sur github (voir # 1579 , # 394 et # 1003 ).

Ce que vous pouvez faire, c'est ce qui se trouve dans cette réponse: analysez la propriété dans une fonction, convertissez la fonction en une chaîne, puis extrayez le nom de la propriété de la chaîne.

Voici une fonction pour faire cela:

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

Ensuite, utilisez-le comme tel:

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

Cela pourrait ne pas fonctionner selon la façon dont le code est minifié, alors faites attention à cela.

Mettre à jour

Il est plus sûr de le faire au moment de la compilation. J'ai écrit ts-nameof, donc c'est possible:

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

Compile à:

 "name";