2015-11-05 58 views
10

我正在尋找一種方法,通過類型檢查來獲取對象屬性名稱,以便在重構後捕獲可能的迴歸。在TypeScript中提取屬性名稱的安全方法

下面是一個示例:我必須將屬性名稱作爲字符串傳遞的組件,如果我嘗試更改模型中的屬性名稱,它將被破壞。

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

我很感激,如果有什麼好的解決方案來解決這個問題。

+1

目前在GitHub上的一些建議與此幫助(參見[#1579](https://github.com/Microsoft/TypeScript/issues/1579),[#394](HTTPS: //github.com/Microsoft/TypeScript/issues/394)和[#1003](https://github.com/Microsoft/TypeScript/issues/1003))。您可以查看[this](http://stackoverflow.com/a/32542368/188246),但要注意,代碼縮小後可能無法使用。 –

+0

@DavidSherret你的'這個'解決方案是我能想出的唯一答案。請作爲回答 – basarat

+0

@basarat會做,謝謝!對於a => a, –

回答

9

在TS 2.1 keyof關鍵字引入這使得這一切成爲可能:

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

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

這些可以是使用這樣的:

propertyOf<MyObj>("myProperty"); 

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

如果myProperty的是不是類型MyObj中的屬性這將給出一個錯誤。

+0

這很好。這裏是如何將它添加到類中的示例 https://gist.github.com/anonymous/5d5d041b4671480855070af478eb3fc2 –

16

現在還沒有真正做到這一點的好方法,但目前在github上有一些開放的建議(請參閱#1579,#394#1003)。

你可以做什麼,就是this answer -wrap在函數中引用屬性,將函數轉換爲字符串,然後從字符串中提取屬性名稱。

這裏有一個函數來做到這一點:

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"; 
+0

。屬性我發現我需要從正則表達式中刪除'\}' –