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.
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
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";
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é.