2015-11-05 5 views
10

Ich bin auf der Suche nach einer Möglichkeit, einen Objekteigenschaftennamen mit Typchecking zu erhalten, der nach dem Refactoring mögliche Regressionen abfangen kann.Sicherer Weg zum Extrahieren von Eigenschaftsnamen in TypeScript

Hier ist ein Beispiel: Die Komponente, wo ich die Eigenschaftsnamen als Zeichenfolgen übergeben muss, und es wird gebrochen, wenn ich versuche, die Eigenschaftsnamen im Modell zu ändern.

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

Ich würde mich freuen, wenn es eine nette Lösung zur Lösung dieses Problems gibt.

+1

Es gibt derzeit einige Vorschläge auf Github mit diesem zu helfen (siehe [# 1579] (https://github.com/Microsoft/TypeScript/issues/1579) [# 394] (https: //github.com/Microsoft/TypeScript/issues/394) und [# 1003] (https://github.com/Microsoft/TypeScript/issues/1003)). Sie können [this] (http://stackoverflow.com/a/32542368/188246) auschecken, aber Vorsicht, es funktioniert möglicherweise nicht, sobald der Code minimiert wurde. –

+0

@DavidSherret Ihre 'This' Lösung ist die einzige Antwort, die ich auch finden kann. Bitte als Antwort senden – basarat

+0

@basarat wird tun, danke! –

Antwort

9

In TS 2.1 das keyof Schlüsselwort wurde eingeführt, die möglich, dies gemacht:

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

oder

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

Diese können dann sein wie folgt verwendet:

propertyOf<MyObj>("myProperty"); 

oder

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

Dies wird einen Fehler, wenn myProperty nicht eine Eigenschaft des Typs MyObj ist.

+0

Das ist großartig. Hier ist ein Beispiel, wie es zu einer Klasse https://gist.github.com/anonymous/5d5d041b4671480855070af478eb3fc2 hinzugefügt werden kann –

16

Im Moment gibt es nicht wirklich eine gute Möglichkeit, dies zu tun, aber es gibt derzeit einige offene Vorschläge zu Github (Siehe #1579, #394 und #1003).

Was Sie tun können, ist, was in this answer angezeigt wird -Wrap Verweis auf die Eigenschaft in einer Funktion, konvertieren Sie die Funktion in eine Zeichenfolge, extrahieren Sie dann den Namen der Eigenschaft aus der Zeichenfolge.

Hier ist eine Funktion zu tun, dass:

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

es dann wie so verwenden:

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

Dies könnte nicht abhängig von arbeiten, wie der Code minimiert ist so nur für die aufpassen.

aktualisieren

Es ist sicherer, das bei der Kompilierung zu tun. Ich schrieb ts-nameof so ist dies möglich:

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

Compiliert zu:

"name"; 
+0

für a => a.Eigenschaft Ich fand, dass ich das '\}' von der Regex entfernen musste –

Verwandte Themen