2017-11-11 186 views
0

我正在關注Typescript的Pluralsites課程。當與接口的工作,我有以下幾點:Typescript接口可選方法屬性未定義

interface Book { 
    id: number; 
    title: string; 
    author: string; 
    available: boolean; 
    category: Category; 
    pages: number; 
    markDamaged: DamageLogger; 
} 

interface DamageLogger { 
    (reason: string): void; 
} 

我現在宣佈一本書中:

let myBook: Book = { 
    id: 5, 
    title: 'Pride and Prejudice', 
    author: 'Jane Austen', 
    available: true, 
    category: Category.Fiction, 
    pages: 250, 
    markDamaged: (reason: string) => console.log('Damaged: ' + reason) 
}; 

myBook.markDamaged('missing back cover'); 

一切都很好,但只要我改變接口的markDamaged是可選如:

interface Book { 
    id: number; 
    title: string; 
    author: string; 
    available: boolean; 
    category: Category; 
    pages: number; 
    markDamaged?: DamageLogger; 
} 

該行的編譯器樹皮:

myBook.markDamaged('missing back cover'); 

並說markDamaged屬性可能是未定義的。我刪除了問號,一切都很好。

任何想法這是怎麼回事?我在課程的其他地方使用可選參數,但是在使用接口時,這是我所看到的。

感謝您的幫助。

+0

那麼,因爲markDamaged被標記爲可選項,所以它不可能存在於對象中。如果它不存在,它是未定義的。所以你需要在調用它之前檢查它是否存在。 –

回答

0

如果你的狀態markDamaged?: DamageLogger,你的意思是一個Book可能會或可能不會有markDamaged財產。然後,編譯器會強制您檢查Book(包括myBook)實際上是否有markDamaged,然後它會讓您調用它。此檢查僅在設置--strictNullChecks編譯器選項時啓用。

這工作

interface Book { 
    markDamaged: DamageLogger 
} 
interface DamageLogger { 
    (reason: string): void 
} 

let myBook: Book = { 
    markDamaged: (reason: string) => console.log('Damaged: ' + reason) 
} 
// myBook: Book; it definitely has markDamaged 
myBook.markDamaged('missing back cover') 

這不

interface Book { markDamaged?: DamageLogger } 
// ... 
// myBook: Book; Books do not definitely have markDamaged 
myBook.markDamaged('...') 

但這確實

if(myBook.markDamaged) { 
    // Now we know it's there, we can call it 
    myBook.markDamaged('...') 
} 

這也適用於:

interface Book { markDamaged?: DamageLogger } 
// don't say it's a Book 
// inferred: myBook: { markDamaged: (reason: String) => void } 
// TypeScript's type system is structural, not nominal 
// The identity of a type is in it's structure, not name 
// myBook's type says that it definitely has markDamaged 
let myBook = { markDamaged: (reason: String) => console.log('Damaged: ' + reason) } 
myBook.markDamaged('...') 

function read(b: Book) {} 
// myBook's type is a subtype of Book, because a Book can be missing markDamaged but myBook definitely has it. 
read(myBook) 
+0

男人,這個真的很奇怪。如果將界面中的頁面屬性設置爲可選,我可以稱之爲: myBook.pages = 10.因爲'markDamaged'是一種方法,所以它不喜歡它。 –

+0

編譯器選項有竅門。 –

+0

您正在設置屬性;所以它會被創建,如果它丟失。它是否是可選的並不重要。 – HTNW

0

這是因爲它不能保證被定義。先檢查它,編譯器應該停止抱怨。

if (myBook && myBook.markDamaged) { 
    myBook.markDamaged('missing back cover'); 
}