2016-03-07 80 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