web-dev-qa-db-fra.com

Un moyen sûr d'extraire les noms de propriété

Je cherche un moyen d'obtenir un nom de propriété d'objet avec un contrôle de type qui permet d'attraper les régressions possibles après refactoring.

Voici un exemple: le composant où je dois passer les noms de propriété sous forme de chaînes et il sera cassé si j'essaye de changer les noms de propriété 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 bonne solution pour résoudre ce problème.

24
shadeglare

Dans TS 2.1, le mot clé keyof a été introduit, ce qui a rendu cela possible:

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

ou

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

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

propertyOf<MyInterface>("myProperty");

ou

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

ou

const myInterfaceProperties = propertyNamesOf(myObj);
myInterfaceProperties("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

32
nzjoel

Pour le moment, il n'y a pas vraiment un excellent moyen de le faire, mais il y a actuellement quelques suggestions ouvertes sur github (Voir # 1579 , # 394 , et # 100 ).

Ce que vous pouvez faire, c'est ce qui est indiqué dans cette réponse - encapsuler référençant la propriété dans une fonction, convertir la fonction en chaîne, puis extraire le nom de la propriété de la chaîne.

Voici une fonction pour le faire:

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

Ensuite, utilisez-le comme ceci:

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

Cela peut ne pas fonctionner en fonction de la façon dont le code est minimisé, alors faites attention à cela.

Mise à jour

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

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

Compile vers:

"name";
26
David Sherret

Ceci est spécifiquement destiné aux développeurs React/React-Native.

Pour obtenir en toute sécurité le nom de la propriété, j'utilise la classe ci-dessous:

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

Et remplacé extends React.Component<PropTypes> Par extends BaseComponnent<PropTypes,

Maintenant, avec dans le Component vous pouvez appeler, this.getPropName('yourPropName') pour obtenir le nom de la propriété.

2
theapache64