【发布时间】:2017-06-21 00:55:14
【问题描述】:
2021 年更新
有关使用新功能的有效解决方案,请参阅此答案https://stackoverflow.com/a/59647842/1323504
我正在尝试编写一个函数,我想指出它返回 某种 纯 JavaScript 对象。该对象的签名是未知的,目前也不感兴趣,只有它是一个普通对象的事实。我的意思是一个普通对象,它满足例如 jQuery 的 isPlainObject 函数。例如
{ a: 1, b: "b" }
是一个普通的对象,但是
var obj = new MyClass();
不是“普通”对象,因为它的 constructor 不是 Object。 jQuery 在$.isPlainObject 中做了一些更精确的工作,但这超出了问题的范围。
如果我尝试使用Object 类型,那么它也将兼容任何自定义对象,因为它们继承自Object。
有没有办法在 TypeScript 中定位“普通对象”类型?
我想要一个 type,例如,它会满足这个要求。
var obj: PlainObject = { a: 1 }; // perfect
var obj2: PlainObject = new MyClass(); // compile-error: not a plain object
用例
我有一种用于服务器端方法的强类型存根,就像这样。这些存根由我的一个代码生成器生成,基于 ASP.NET MVC 控制器。
export class MyController {
...
static GetResult(id: number): JQueryPromise<PlainObject> {
return $.post("mycontroller/getresult", ...);
}
...
}
现在当我在消费者类中调用它时,我可以做这样的事情。
export class MyViewModelClass {
...
LoadResult(id: number): JQueryPromise<MyControllerResult> { // note the MyControllerResult strong typing here
return MyController.GetResult(id).then(plainResult => new MyControllerResult(plainResult));
}
...
}
现在假设控制器方法返回JQueryPromise<any> 或JQueryPromise<Object>。现在还想象一下,我偶然写了done而不是then。现在我有一个隐藏的错误,因为 viewmodel 方法不会返回正确的承诺,但我不会得到一个编译错误。
如果我有这个虚构的PlainObject 类型,我预计会收到一个编译错误,指出PlainObject 不能转换为MyControllerResult,或类似的东西。
【问题讨论】:
-
最后,这意味着您几乎可以接受
any值,因为Javascript 中的几乎所有内容都是一个对象,您甚至都不关心它的任何特定特征。您的函数的调用者可能会出于自己的目的决定将您想要的对象实现为一个类;生成的对象仍将与您预期的“普通”对象完美兼容,特别是如果您甚至不关心该对象的任何内容。虽然是一个有趣的问题,但我有点看不出它的实用性。 -
您通常键入提示来强制执行对象的特定特征;您究竟为什么要为特定特征的absence 键入提示?方法是否返回一个类真的不应该,这是一个实现细节。只要该类实例仍然符合预期的行为,在本例中为
any,这无关紧要。 -
@ZoltánTamási 事情是这样的:类型用于执行合同。如果您没有特定的合同,那么您就不能期望静态地强制输入。然而,同样,由于
MyControllerResult要求对象具有一些特定的 属性,您应该记录这些属性,然后将其用作您的类型。我看不到PlainObject在这里有什么用处。 -
这样的事情怎么样?typescriptlang.org/play/…
-
@ZoltánTamási 真的不是。您只是说它应该是
Object,但这并没有告诉您有关您期望的数据类型的任何信息。请向我解释为什么根据您将收到的数据类型(即您希望对象具有哪些属性)来定义您的合同是一个坏主意。现在看来你只是专注于应用你有缺陷的想法,而不是纠正你的方法。
标签: javascript typescript typescript2.1