我玩过一些打字稿,发现了这个:
class Greeter {
e: number;
p: boolean = true;
}
const xxx = new Greeter(); // true
console.log(xxx instanceof Greeter);
const xxx2: Greeter = { e: 1, p: true }; // <--- 1. why is this valid?
console.log(xxx2 instanceof Greeter); // false
const xxx3: Greeter = Object.setPrototypeOf({ e2: 1 }, Greeter.prototype); // <-- 2. no warning?
console.log(xxx2 instanceof Greeter); // true
所以我的问题是:
为什么在typescript中将动态对象分配给类对象是有效的,而不是真正的类。它似乎不是真正的阶级。这会在未来有所改善吗?
似乎是黑客攻击。但是类型没有干净的Typescript函数。这应该更干净,有更好的检查功能吗?
我使用Typescript 2.4.2和严格的选项。
答案 0 :(得分:2)
为什么在typescript中将动态对象分配给类对象是有效的,而不是真正的类。它似乎不是真正的阶级。
TypeScript是一种结构语言,而不是名义语言。这意味着检查结构,并且可以使用任何兼容类型。一旦你开始依赖这种语言功能,名义上的打字就会让你疯狂。
将来会有所改善吗?
无法改进!结构类型摇滚:)。
但我认为正确答案是“不 - 这是设计”。
const xxx3: Greeter = Object.setPrototypeOf({ e2: 1 }, Greeter.prototype);
似乎是黑客攻击。但是类型没有干净的Typescript函数。这应该更干净,有更好的检查功能吗?
这个需要一点点解构。
第一部分是TypeScript中有一个动态类型:any
。任何类型为any
的东西都像变形者。它实际上可以是任何类型。
只要您希望编译器不受影响并允许您使用动态类型,就可以使用any
。 (动态,如“类型可以动态更改”,我注意到您将对象文字描述为动态 - 但我在这里谈论的是官方动态类型。)
当您致电Object.setPrototypeOf(...)
时,它会返回其中一种特殊动态类型,其类型为any
。
这意味着,当您将其分配给类型为Greeter
的变量时,它是允许的,因为您有any
类型。
虽然这可能令你感到沮丧,但我确信你想要达到的目标是可能的 - 所以请随时询问如何实现你需要做的事情,我相信我们会来一种帮助的方式
答案 1 :(得分:0)
由于打字稿只进行编译时检查。
如果您使用以下链接并粘贴代码并获取JavaScript
const xxx2: Greeter = { e: 1, p: true };
converts to -->
var xxx2 = { e: 1, p: true };
这只是一个对象,对类Greeter
答案 2 :(得分:0)
@ Fenton的正确answer对于TypeScript支持的结构打字是值得称赞的传福音。然而,对于那些发现自己对nominal typing的禁果有趣的想法的场合,确实存在变通方法:
我建议您Greeter
private member,以便您不再为其分配对象字面值。私有类成员似乎是名义键入的“标准”TypeScript解决方法。
示例:
class Greeter {
private _nominal = true; // add something like this
e: number;
p: boolean = true;
}
const xxx = new Greeter();
const xxx2: Greeter = { e: 1, p: true }; // error, missing _nominal
const xxx3: Greeter = { e: 1, p: true, _nominal: true }; // error, _nominal is private
这对你有用吗?这至少会让自己陷入困境更加困难,尽管如果你真的尝试,你会成功:
// don't do this
const xxx4: Greeter = function() { return "ha ha fooled you";} as any as Greeter;
希望有所帮助;祝你好运!