2016-03-07 84 views
0

我注意到以下行爲:類型斷言VS性能

interface User { 
    name: string; 
    age: number; 
} 

let user:User = { 
    name: "Aaron", 
    age: 99 
} 

如果我省略age: 99我得到一個編譯錯誤。 這是我期望的行爲。

但是:

function putUser(user:User):void { } 

putUser(<User> { 
    name: "Aaron" 
}); 

我得到缺少非可選屬性age沒有編譯錯誤。

事實上,在我真正的代碼庫,我發現用 鑄造 類型斷言我有時可以添加完全錯誤的屬性的對象字面,但我無法重現的這種行爲簡單的情況就像上面。

任何人都可以解釋這裏發生了什麼?


編輯:省略斷言作品,感謝@Amid。然而,當我遇到了這個作爲一個問題是這樣的情景:

interface User { name: string; } 

function putUser(user:User):void { } 

interface Musician extends User { instrument: string; } 

putUser(<Musician> { 
    name: "Bob Dylan" 
}); 

的問題是,我想驗證Musician對象,但只putUser預計該基地User對象。我認爲類型斷言會給我更好的類型安全性,但在這種情況下,它實際上減少了類型安全性。


編輯#2

它看起來像我能得到我想要使用泛型類型約束,這實際上看起來一個可怕的很多像我喜歡的類型聲明:

function putUser<T extends User>(user:T):void { } 

putUser<Musician>({ 
    name: "Bob Dylan", 
    instrument: "Guitar" 
}); 

在這種情況下,它似乎會確保對象文字恰好是Musician的實現。

+0

望着規範,' obj'不是演員,而是一個說法,'obj'已鍵入'User'。類型斷言不會在運行時檢查,請參閱[這裏](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#4.16) – Lee

+0

是的,你是對的我把它稱爲一個演員,但它是一個斷言......是否有一個「真正的」演員,然後呢? – Aaron

+0

這是[文檔](https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#typescript-16)繞過「嚴格的對象字面值分配檢查」的方法之一。 –

回答

2

原因是你在這裏使用type assertion。這基本上覆蓋了所有打字稿類型檢查。如果刪除 <用戶>部分 - 編譯器會給你錯誤你想到

編輯:

這是你想要什麼:

interface User { name: string; } 

function putUser<T extends User>(user:T):void { } 

interface Musician extends User { instrument: string; } 

putUser<Musician>({ 
    name: "Bob Dylan" 
}); 
1

你犯了一個類型的斷言。如果您具有要接收的數據的形狀,但沒有自己的數據源,則在與外部系統(如請求API)通信時,您更願意使用類型斷言。

typescript斷言很聰明。它不會讓你做出完全錯誤的事情。這裏有一個例子:

interface Point { 
    x: number; 
    y: number; 
} 

function process(box: Point) {} 

let empty = {}; 
let part = { x: 3 }; 
let full = { x: 3, y: 5 }; 
let vague = { x: 3, y: 5, z: 7 }; 

process(empty); //type mismatch, got {} expected {x, y} 
process(part); //type mismatch, only {x} expected {x, y} 
process(null); //no type mismatch, argument can be null 
process(full); //full match 
process(vague); //still works, but the function is not aware of "z" field. 

process(<Point>empty); //assertion valid, object can be a Point instance 
process(<Point>"123"); //wrong assertion, expected object instead of string 
process(<Point>[]); //wrong assertion, expected object instead of array