2014-07-17 78 views
0

我想這個代碼:如何訪問使用Typescript中的接口聲明的屬性的屬性?

export interface IEnumElement { 
    elem: string; 
    text: string; 
    val: number 
} 
export interface IIndexable<T> { 
    [index: string]: T; 
} 
export class AdminBase { 

    ExamStatusId: IIndexable<IEnumElement> = { 
     All: { 
      elem: "", 
      text: 'Exam Status: All', 
      val: 0 
     }, 
     Current: { 
      elem: "asdf", 
      text: 'Exam Status: Current', 
      val: 1 
     } 
    } 
} 

var x = new AdminBase(); 
var y = x.ExamStatusId.All; 

它給了我一個錯誤說:

Error 1 The property 'All' does not exist on value of type 
'IIndexable<IEnumElement>'. C:\Protractor\TypeScript1.ts 

注意ExamStatusId現在只有兩個特性,但有可能是任何數量的不同性質的後面。

回答

1

請查看我對上一個問題的回答......您會看到我的解決方案實際上允許訪問All屬性。

Can I define an interface for every property of an object just the one time?

再次,我就會在打字稿強調扶着類型推斷之美。您不需要明確註釋程序中的所有內容,您可以讓編譯器和語言服務完成艱苦的工作。

「類型推斷版」你的代碼爲您提供:

  • 爲IEnumElement類型安全的消費點
  • 類型安全性ExamStatusId財產如果你使用它作爲一個IEnumElement
  • 訪問All屬性
  • 較少手寫註釋

下面是完整的例子:

interface IEnumElement { 
    elem: string; 
    text: string; 
    val: number 
} 

class Exam { 
    private examStatusSelectId: number; 

    ExamStatusId = { 
     All: { 
      id: this.examStatusSelectId, 
      elem: '', 
      text: 'Exam Status: All', 
      val: 0 
     }, 
     Current: { 
      id: this.examStatusSelectId, 
      elem: '', 
      text: 'Exam Status: Current', 
      val: 1 
     } 
    } 
} 

// This function must be passed an IEnumElement 
function example(element: IEnumElement) { 

} 

var exam = new Exam(); 

// The compiler knows this is good 
example(exam.ExamStatusId.All); 
+0

我們在這裏看到的是,您正在使用「考試」類型。這是一種定義的類型*原樣* ...但這不是OP案例 - 即使這可以解決問題;)。我試圖解釋TypeScript字典是如何工作的 - 例如類型如'IIndexable '。所以,雖然你的例子工作正在改變實現(這仍然是正確的);) –

+0

TypeScript允許我們將許多現有的基於類的知識帶入JavaScript。我們應該在可能的情況下留下我們對名義類型系統的認識,並採用結構類型系統。如果我們使用TypeScript是因爲它給了我們靜態類型檢查,那麼任何需要魔術字符串的解決方案都不如靜態類型的解決方案。另外,實現沒有什麼不同,它只是由編譯器而不是程序員表達。 – Fenton

1

這裏的關鍵是,我們申報的ExamStatusId類型爲實現這個接口IIndexable<IEnumElement>

ExamStatusId: IIndexable<IEnumElement> 

而且我們還宣佈,該IIndexable<IEnumElement>是有Tstring鍵和元素:

export interface IIndexable<T> { 
    [index: string]: T; 
} 

所以,這裏如何訪問該成員的唯一方法是通過字符串索引器:

var y = x.ExamStatusId["All"]; 
+0

會不會有改變的方式,如果我是改變[指數:字符串。不得不在字符串中指定「全部」是我試圖避免的一個問題,因爲如果我錯誤地輸入「全部」,我可以看到問題。你認爲我應該回到這個解決方案:http://stackoverflow.com/questions/24781762/is-there-a-better-way-to-emulate-an-enum-with-typescript –

+1

我明白! ;)100%!當我開始使用這個符號時,我想:「嘿,如果我輸入'ExamStatusId [」All「]'而不是'ExamStatusId.All'',我就失去了安全類型......」但是你知道嗎?與純JS的ExamStatusId.All'的表示法也沒有保存...和在JAVA或C#詞典的字...字典是根本不是類型安全..如果你問一個關鍵...檢查它前後期......並在單元測試中......不好,我知道;(......但是... *最後說明:我們總是可以做'( ExamStatusId).all' ......但小'a'而不是'所有'會在稍後導致錯誤... * –

+0

您可以使用'ExamStatusId.All'完全安全地訪問它。查看我的答案。 – Fenton