网站搜索

typescript2.0 - RequireJS 模块返回但不导出的 TypeScript 定义


不使用 TypeScript 的用法

我有一个我无法编辑的 RequireJS 模块

RequireJS 模块:

//app/Router.js
define([], function() {
  return {
    generate: function(route) { /*do something*/ }
  }
});

该模块没有任何导出,但使用 return 语句,它可以在其他 require 模块中通过如下方式使用:

define(['app/Router'], function(router) {
  router.generate('myRoute');
});

我想在 TypeScript 中使用 app/Router.js

变体 1:TypeScript 知道类型,但 JS 有错误

所以我试着制作我的定义模块:

//Router.d.ts
export interface Router
{
    generate(route:string): string;
}
declare let router: Router;
export default router;

在我的 TypeScript 文件中使用它,如下所示:

import router from 'app/Router'

router.generate('something');

将生成该文件:

define(
  ["require", "exports", "app/Router"], 
  function (require, exports, Router_1)
) {
   Router_1.default.generate();
}

问题是默认属性。JS 说不能在 null 上调用 generate。因为 Router_1 已经是我想要的对象。

变体 2:JS 是正确的,但 TypeScript 不知道类型

我也试过:

//Router.d.ts
export interface Router
{
    generate(route:string): string;
}
declare let router: Router;
declare module "router" {
    export = router;
}

像这样使用它:

import * as router from 'app/Router'

router.generate('something');

输出是正确的:

define(["require", "exports", "app/Router"], function (require, exports, router) {
  router.generate();
});

但是 TypeScript 编译器显示:属性 'generate' 在类型上不存在

问题

我的 Router.d.ts 和 import 语句应该长什么样,才能得到正确的输出并让 TypeScript 知道正确的类型?

答案#1

当你使用 export default stuff 时,你是在告诉编译器被导出的对象有一个名为 default 的属性,其值为 stuff,如果在 .js 文件中对象的 object.default == undefined,当作为函数调用时会抛出 TypeError。请尝试以下方法:

//Router.d.ts

declare module "app/Router" { // <- this must contain the path and the file's name;

    const router: { 
        generate: (route: string) => string; 
    }

    export = router;
}

// in the .ts file ...

import * as router from "app/Router";

router.generate("go/some/url");

使用 tsc 2.6.1 这个输出:

define(["require", "exports", "app/Router"], function (require, exports, router) {
                                                               //^^^^^^^
    "use strict";                                              //|||||||      
    exports.__esModule = true; // <- it extends this object that was passed as argument ... 
    router.generate("go/some/url");// <- but this was the desired effect, right?
});

我对 AMD 系统没有任何先前的了解,所以我无法判断在函数体内扩展或设置 exports 对象会有什么后果。我认为所做的更改可能无关紧要,但无论如何最好自己检查一下。