打字稿实例不起作用
Posted
技术标签:
【中文标题】打字稿实例不起作用【英文标题】:TypeScript instanceof not working 【发布时间】:2018-02-08 09:07:29 【问题描述】:我在使用 instanceof 运算符时遇到问题,它似乎不起作用。这是我的代码的一部分:
const results = _.map(items, function(item: Goal|Note|Task, index: number)
let result = ;
if (item instanceof Goal)
result = id: index, title: item.name ;
else if (item instanceof Note)
result = id: index, title: item.content.text ;
else if (item instanceof Task)
result = id: index, title: item.name ;
console.log(item);
console.log(item instanceof Goal);
console.log(item instanceof Note);
console.log(item instanceof Task);
return result;
);
我所有的日志都是假的,这是控制台的样子:
它们都不匹配,尽管明确表示只有 3 种类型是可能的。您还可以看到类型名称为 Goal 的对象本身,所以我不明白为什么它与 instanceof Goal 不匹配。
有什么想法吗?
【问题讨论】:
你是如何生成items
的?它们是通过构造函数创建的吗?如果不是,它们将不是给定类的实例。
您是否复制了对象?通过 JSON.parse 或 Object.assign?
它们是来自 API/http 调用的响应。一定是为什么他们的 typeofs 总是对象而不是特定类型?
@AnimaSola 对。要使instanceof
工作,您需要从构造函数中实际制作它们。否则,它们只是恰好与您想要的对象具有相同形状的对象。
感谢@MikeC,选择使用 hasOwnProperty。
【参考方案1】:
instanceof
仅当它与构造它的函数或类匹配时才会返回 true。这里的item
是一个普通的Object
。
const a = a: 1 // plain object
console.log(a);
// a:1 <-- the constructor type is empty
// a: 1
// __proto__: Object <-- inherited from
a instanceof A // false because it is a plain object
a instanceof Object // true because all object are inherited from Object
如果使用构造函数或类构造,那么 instanceof 将按预期工作:
function A(a)
this.a = a;
const a = new A(1); // create new "instance of" A
console.log(a);
// A a:1 <-- the constructor type is `A`
a instanceof A // true because it is constructed from A
a instanceof Object // true
如果Goal
是Interface
,它只会检查对象的结构而不是其类型。如果Goal
是一个构造函数,那么它应该为instanceof
检查返回true。
尝试类似:
// interface Goal ...
class Goal ... // you will have to change the way it works.
items = [
new Goal()
];
2021 年更新:
最近在玩 Typescript,想出了一个更好的解决方案,可以同时在 Typescript 和 javascript 中使用:
尝试类似:
interface Goal
getCount(): number;
class Goal implements Goal
getCount()
return 3;
function getItemCount(item: Goal | Note | Task)
return item instanceof Goal ? item.getCount() : 'not a goal';
console.log(getItemCount(new Goal())); // 3
console.log(getItemCount('goal')); // 'not a goal';
这里的接口和类同名,所以它们可以同时用作类型和实例检查器。
更改接口Goal
签名或类Goal
签名会抛出类似:
TS2394: This overload signature is not compatible with its implementation signature.
【讨论】:
可悲的是,我遇到了一个案例,其中 typeof 对使用构造函数创建的对象失败。记录它们将显示正确的类型,但检查仍然失败。 @mcvtypeof
不会在 JavaScript 中为您提供类型,typeof 仅适用于原始类型,这意味着您将得到 Object
作为任何类型检查的结果。您可能想尝试比较obj.constructor
。这里是 constructor reference 和 typeof reference
它解释了它是如何工作的,当然。但它没有提供解决方案?
@GopikrishnaS 那是我的错字;我的意思是instanceof
,而不是typeof
。在我的情况下它失败的原因是项目中存在同名的不同类,并且不知何故将一个类导入该文件而不是我的意思。 (我已经将这两个不同但相似的数据模型重构为一个明确的模型。)
@CularBytes 答案是:使用构造函数,否则 instanceof 将不起作用。【参考方案2】:
你也可以使用类型保护来发挥你的优势:
https://basarat.gitbooks.io/typescript/docs/types/typeGuard.html
https://www.typescriptlang.org/docs/handbook/advanced-types.html
例如,如果你对你的类使用文字类型保护:
class Goal
type: 'goal'
...
那么检查就这么简单:
if (item.type === 'goal')
或者您可以编写自己的类型保护:
function isNote(arg: any): arg is Note
// because only your Note class has "content" property?
return arg.content !== undefined;
if (isNote(item))
result = id: index, title: item.content.text ;
【讨论】:
从 API 加载对象时,您仍然需要设置type
。但这比其他人提供的解决方案要简单一些。【参考方案3】:
尝试使用构造函数实例化对象。我也遇到了同样的情况,因为我出于测试目的手动模拟了对象。如果您像以下示例一样创建项目,它应该可以工作:
item: Goal = new Goal(*item values*)
【讨论】:
【参考方案4】:正如@Gopikrishna 指出的那样,从JSON.parse
解析或从API 接收的对象将与您的自定义Class
不匹配,因为它不是通过所需类的new
运算符创建的。
一种解决方法是首先将对象转换为所需的类,然后根据undefined
检查属性。
class User
displayName:string;
id:string;
const user = obj as User;
if (user.displayName!==undefined)
//do your thing here
【讨论】:
以上是关于打字稿实例不起作用的主要内容,如果未能解决你的问题,请参考以下文章