- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在尝试使用时遇到问题 instanceof
在 if-else 语句中使用派生类实例。考虑以下示例:
interface IBaseModel {
id: string
}
class BaseClass {
model: IBaseModel
constructor() {
}
setModel(model: IBaseModel) {
this.model = model
}
getValueByName(name: string) {
return this.model[name];
}
}
interface IDerived1Model extends IBaseModel {
height: number;
}
class Derived1 extends BaseClass {
setModel(model: IDerived1Model) {
super.setModel(model);
// Do something with model...
}
}
interface IDerived2Model extends IBaseModel {
width: number;
}
class Derived2 extends BaseClass {
setModel(model: IDerived2Model) {
super.setModel(model);
// Do something with model...
}
}
const model1 = { id: "0", height: 42 };
const model2 = { id: "1", width: 24 };
const obj1 = new Derived1();
obj1.setModel(model1);
const obj2 = new Derived2();
obj2.setModel(model2);
const objs: BaseClass[] = [
obj1,
obj2
];
let variable: any = null;
for (const obj of objs) {
if (obj instanceof Derived1) {
variable = obj.getValueByName("height"); // Ok, obj is now of type `Derived1`
} else if (obj instanceof Derived2) {
variable = obj.getValueByName("width"); // Does not compile: Property 'getValueByName' does not exist on type 'never'
}
console.log("Value is: " + variable);
}
getValueByName
无法调用
obj
在
else
部分,因为它缩小到
never
.不知何故,Typescript 认为
else
永远不会被执行,但这是错误的。
setModel
的覆盖。 .覆盖有不同的参数类型,但这些类型继承自基
IBaseModel
类型。如果我将它们更改为基本类型,Typescript 不会提示并且可以正常编译:
class Derived1 extends BaseClass {
setModel(model: IBaseModel) {
super.setModel(model);
// Do something with model...
}
}
class Derived2 extends BaseClass {
setModel(model: IBaseModel) {
super.setModel(model);
// Do something with model...
}
}
instanceof
运算符将对象的类型缩小到
never
?这是故意的吗?
最佳答案
欢迎来到 TypeScript Issue #7271 的世界!你被 TypeScript 的 structural typing 咬了以及它与 instanceof
的奇怪(坦率地说是不健全的)互动.
typescript 见 Derived1
和 Derived2
作为完全相同的类型,因为它们具有相同的结构形状。如 obj instanceof Derived1
返回 false
,TypeScript 编译器认为“好吧,obj
不是 Derived1
”和“好吧,obj
不是 Derived2
”,因为它没有看到它们之间的区别。然后当您检查 obj instanceof Derived2
时返回 true
,编译器说“哎呀,obj
既是又不是 Derived2
。这可能发生 never
。”当然Derived1
是有区别的和 Derived2
在运行时,这可能会发生。这是你的问题。
解决方案:将一些不同的属性放入 Derived1
和 Derived2
这样 TypeScript 就可以分辨出它们之间的区别。例如:
class Derived1 extends BaseClass {
type?: 'Derived1'; // add this line
setModel(model: IDerived1Model) {
super.setModel(model);
// Do something with model...
}
}
class Derived2 extends BaseClass {
type?: 'Derived2'; // add this line
setModel(model: IDerived2Model) {
super.setModel(model);
// Do something with model...
}
}
type
每个类的属性具有不同的字符串文字类型(不更改发出的 JavaScript)。 TypeScript 现在意识到
Derived1
与
Derived2
不一样你的错误就会消失。
Thanks for the explanation! However, I fail to see why Typescript considers them structurally identical when the types of the parameter in the override is different, but everything compiles fine when the type is identical (i.e. the same as the parent,
IBaseModel
). Also, what happens if I already have a member calledtype
on my object? Can it conflict withtype
? ?. Thanks!
setModel
具有更窄参数类型的方法(顺便说一句,这是不合理的......每个
BaseClass
都应该有一个
setModel()
接受任何
IBaseModel
。如果你有兴趣做到这一点,我们可以谈谈),它是愚蠢的#10216 中的代码更改为不应用。这可能是一个错误...你可能想要
file it .
__typeBrand
如果您担心意外冲突。
class Derived1 extends BaseClass {
model: IDerived1Model;
// your overrides follow
}
class Derived2 extends BaseClass {
model: IDerived2Model;
// your overides follow
}
model
是窄型的吧?所以做上述缩小
model
两者都让编译器知道类型在结构上是不同的,并使派生类使用起来更安全。
关于在 if-else 语句中使用 instanceof 将 typescript 类型缩小到从不,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45381122/
对于以下条件: if (a != null && a instanceof A) 或 if (a instanceof A) 首先检查 null 是否有任何优势(例如,性能方面)?两个条件的结果应该相
我正在编写一个方法,如果异常是 *someClass* 的实例,它将返回 true。但是我无法导入其中一个类,因为它在另一个模块中。我无法将该模块添加到项目中,所以我想,我不能使用 instanceo
这个问题在这里已经有了答案: The difference between "instanceof List" and 'o instanceof List" (2 个答案) 关闭 7 年前。 我知
多年来,我尽量避免使用 instanceof。在适用的情况下使用多态性或访问者模式。我想它只是在某些情况下简化了维护......还有其他需要注意的缺点吗? 但是我确实在 Java 库中到处看到它,所以
我没有看到以下任何区别: Object o = new LinkedList(); System.out.println(o instanceof List); System.
我正在像这样扩展对象: Object.prototype.is_a = function (x) { return this instanceof x; } 一切正常 "foo".is_a(Str
我在 NetBeans 中编码如下: public class Grafo { class Par { int a, b; Par(int a, int
我已经动态创建了布局。它有一些编辑文本、 TextView 、微调器等。 之后,我必须获取我介绍的关于这些 View 的信息。 所以我在做这样的事情 for(int i=0;i <= childs;i
等等!我知道还有其他非常相似的问题,但(也许是我)我需要回答其中的特定部分。 我知道可以说 Object.prototype 位于委托(delegate)链的最顶端。但是,在 Function 存在以
MooTools 有自己的instanceOf(instance, Type) 函数。 我只能假设它做了一些与 Javascript 的原生 instanceof 运算符不同的事情,但我似乎无法弄清楚
获取UTXO的方法 getUtoxs(address){ var options; if(Global.btc.network === "testnet"){ options = {
为什么在 JavaScript 中,Object instanceof Function 和 Function instanceof Object 都返回 true? 我在 Safari WebIns
为什么在 JavaScript 中 Object instanceof Function 和 Function instanceof Object 都返回 true? 我在 Safari WebIns
首先,我制作了一个“游戏渲染器”。 我的问题是,当我需要绘制当前元素时:我需要知道它是矩形、圆形还是图像等。 我的类(矩形、圆形...)是从图形扩展而来的。 public class Rectangl
想象一下,我想编写一个名为 isInstanceof 的无用方法,它返回一个 boolean。 我在想。但我不出去。 instanceof 必须像这样使用: [object] instanceof [
我有两个继承自 Player 的类:SimplePlayer 和 InterleavedPlayer。 B 类有这些方法:setPlayer(SimplePlayer player) 和 setPla
我在尝试使用以下内容时遇到了意外行为: $object instanceof $class 1/如 in the official doc. 所述,PHP 'instanceof' 关键字和命名空间可
可以在 angularjs 中使用 typeof 吗? 我有一个 ngrepeat 循环遍历我的数据,应该检查数据是字符串还是对象。 {{angular.isObject(text) &&
例如,我有 Currency 和处理 Currency 各种实现的 Exchange。我想对窗帘货币有额外的汇率,我这样做 interface Currency { double rate();} i
我有以下代码: abstract class BaseToken {} class OpenParen extends BaseToken { public static assert(t:
我是一名优秀的程序员,十分优秀!