【发布时间】:2015-11-18 03:50:28
【问题描述】:
问题:
有什么方法可以在 TypeScript 中编写类型注释,允许任何对象字面量,但不允许内置类型 number、string、boolean、Function 或 Array?
为什么?
我一直在努力改进我在工作项目中使用的一些库的相关类型定义。我在许多 JS 库中注意到的一个常见模式是传递一个用于配置库或插件的“选项”对象。在这些情况下,您通常会看到类似这样的类型定义:
declare module 'myModule' {
interface IMyModule {
(opts?: IOptions): NodeJS.ReadWriteStream;
}
interface IOptions {
callback?: Function;
readonly?: boolean;
}
}
这允许你像这样使用它:
var myModule = require('myModule');
myModule();
myModule({});
myModule({ callback: () => {} });
myModule({ readonly: false });
myModule({ callback: () => {}, readonly: false });
这些都是有效的用例。问题是这些类型定义也允许这些无效的用例:
myModule('hello');
myModule(false);
myModule(42);
myModule(() => {});
myModule([]);
在许多情况下,上述调用会导致运行时错误,因为库 JS 代码可能会尝试在对象上设置默认值,或者将选项传递给另一个库。尽管我尝试了很多事情,但我无法将参数限制为仅接受对象而不接受任何其他无效情况。
如果你有一个只有可选成员的接口(因为不需要任何一个选项),编译器会扩大可接受的类型以接受any。
你可以在这里看到这个问题的 TypeScript Playground 演示:http://bit.ly/1Js7tLr
更新:不起作用的解决方案示例
interface IOptions {
[name: string]: any;
callback?: Function;
readonly?: boolean;
}
此尝试要求对象上存在索引运算符,这意味着它现在抱怨numbers、strings、booleans、Functions 和Arrays。但这又带来了一个新问题:
var opts = {};
myModule(opts);
当它应该是一个有效的场景时,它现在失败了。 (在操场上看到这个:http://bit.ly/1MPbxfX)
【问题讨论】:
-
我看过这个:github.com/Microsoft/TypeScript/pull/3823,但我不确定这是否解决了这个问题,它是 v1.6。如果可能的话,我很想在 1.5 中找到一种方法来实现这一点。
-
您可能只需要运行大量检查,我想这没什么好说的。所有这些案例都可能对您有所帮助:tobyho.com/2011/01/28/checking-types-in-javascript
-
@ZacharyDow,在这里我实际上并不是在编写 JavaScript 库,而是在编写描述现有 JavaScript 库 API 的 TypeScript 类型定义(请参阅 github.com/borisyankov/DefinitelyTyped)。我无法控制最终将被调用的代码。我的目标是帮助 TypeScript 用户在将错误类型作为选项传递时获得编译错误,因此他们不会错误地认为它会因为它编译而工作。如果没有这些编译时错误,用户就无法确信定义是正确或有用的。
标签: typescript definitelytyped