为什么TypeScript没有实现Type Casting而只是Type Assertion?我没有为我的代码寻找答案,但是因为TypeScript中没有实现Type Casting,以及为什么我们不应该(假设!)自己实现它。
实施例。我是一个TypeScript前端,通过AJAX调用从后端接收JSON数据,元素中包含元素。这是关于食物的,你必须付出代价,乘以一天中的小时。
我们得到了这个JSON:
{
"food" : [{
"name" : "pizza",
"price" : 1.234
"ingredients" : [
"name" : "cheese",
"extra_price" : 1.2345
]
}
]
}
我们有这些课程:
class Food {
public name : string;
public price : number;
public ingredients : Ingredient[];
public timePrice() : number {
return this.price * (new Date()).getHours();
}
}
class Ingredient {
public name : string;
public extra_price : number;
}
如果我们使用TypeScript投射此类型,我们可以完美地使用属性,包括成分。完美。
但是:我们不能使用timePrice函数。因为TypeScript执行Type Assertion和NOT Type Casting。
我知道在将属性作为参数传递时可以编写构造函数的选项,但是如果元素中的元素中有元素:不是选项。所以解决这个问题的唯一方法是创建一个带有静态函数和Food和Ingredient作为参数的Utils类。那是在工作。
但为什么呢?类型转换有什么问题,它没有在TypeScript中实现?对我来说,构建它似乎并不那么难,但是因为MicroSoft没有这样做,所以这样做必然存在难以克服的问题。
答案 0 :(得分:2)
对于具有原始属性的顶级对象,就像你在这里拥有的那个,你当然可以改变对象的原型以指向类原型而大多数的东西会像你一样工作期望的。
但是这样的课呢?
class Food extends Something {
name: string;
price: number;
eat = () => { super.consume(); };
}
在这里,每次调用new Food()
时,我们都会获得eat
属性的新闭包。现在编译时转换为Food
需要创建一个新的闭包,以某种方式找到对超类的consume
方法的正确引用(这是不琐碎 - 它可能无法从当前范围访问!),重新绑定它(这不能在ES6中以100%保真度完成),并将其复制。所以有一个问题就是蝙蝠。
情况变得更糟。假设您有一组这样的类:
class ShoppingCart {
items: Array<Food | Sundry>;
}
class Food {
name: string;
calories?: number;
eat() { }
}
class Sundry {
name: string;
brand?: string;
use() { }
}
然后你写
var x: ShoppingCart = <ShoppingCart>{ items: [
{ name: 'ace' },
{ name: 'avocado', calories: 130 },
{ name: 'triscuits', brand: 'kraft', calories: 100 }
]};
这越来越糟糕了!现在我们必须弄乱根对象,和迭代对象来设置它们的原型。这变得非常复杂。但它仍然更糟...... { name: 'ace' }
元素既是有效的Food
又是有效的Sundry
!我们把它投到哪个?并且triscuits
元素也是模糊的 - 我们应该做什么?
这仍然会变得更糟 - 我们可能无法从此代码获取Food
或Sundry
的运行时引用。您可能只是从某个模块导入了ShoppingCart
而未导入Food
或Sundry
。
我们仍未解决像
这样的问题