web-dev-qa-db-ja.com

プロパティ名を抽出する安全な方法

リファクタリング後に起こり得るリグレッションをキャッチできるタイプチェックを使用してオブジェクトプロパティ名を取得する方法を探しています。

次に例を示します。プロパティ名を文字列として渡す必要があるコンポーネント。モデルのプロパティ名を変更しようとすると壊れます。

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

この問題を解決するニースのソリューションがあれば感謝します。

24
shadeglare

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

32
nzjoel

現時点ではこれを行うのに最適な方法はありませんが、現在、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";
26
David Sherret

これは特に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_に置き換え、

これで、Componentthis.getPropName('yourPropName')を呼び出してプロパティ名を取得できます。

2
theapache64