systemjs导入出错

importing goes wrong with systemjs

我正在尝试在客户端和服务器中使用现有的 js 库 (validate.js)。

我使用 npm 安装它,所有内容都可以为服务器和客户端编译。
在服务器上使用它时效果很好,但是当我在浏览器中执行它时它会抛出错误。

两种情况下使用相同的文件:

import validate = require("validate.js");

export function RequestValidator(data: any): any {
    return (validate as any)(data, constraints, { allowEmpty: true });
}

validate 被断言为 any 因为否则我得到:

TS2349: Cannot invoke an expression whose type lacks a call signature.

我使用的.d.ts是:

declare module "validate.js" {
    export interface ValidateJS {
        (attributes: any, constraints: any, options?: any): any;
        async(attributes: any, constraints: any, options?: any): Promise<any>;
        single(value: any, constraints: any, options?: any): any;
    }

    export const validate: ValidateJS;
    export default validate;
}

该模块仅导出一个函数,在服务器端运行良好,但在客户端调用此函数时我得到:

Uncaught TypeError: validate is not a function(…)

代码是使用目标 commonjs 为服务器编译的:

"use strict";
const validate = require("validate.js");
...

system 客户:

System.register(["validate.js"], function(exports_1, context_1) {
    "use strict";
    var __moduleName = context_1 && context_1.id;
    var validate;
    ...

    return {
        setters:[
            function (validate_1) {
                validate = validate_1;
            }],
    ...

调试时,validate 确实不是一个函数,它是:

validate: r
    EMPTY_STRING_REGEXP: (...)
    get EMPTY_STRING_REGEXP: function()
    set EMPTY_STRING_REGEXP: function()
    Promise: (...)
    get Promise: function()
    set Promise: function()
    __useDefault: (...)
    get __useDefault: function()
    set __useDefault: function()
    async: (...)
    get async: function()
    set async: function()
    capitalize: (...)
    get capitalize: function()
    set capitalize: function()
    cleanAttributes: (...)
    get cleanAttributes: function()
    set cleanAttributes: function()
    ...

知道发生了什么以及为什么它在浏览器中以这种方式运行吗?

使用 "module": "system" 编译时,节点兼容导入

import validate = require("validate.js");

不再有效 - 您为 validate 获得的值是一个模块,而不是一个函数。这可能是打字稿中的错误,也可能是设计使然 - 我不知道。 (更新:来自 github 发给 JsonFreeman here 的评论,看起来像是设计使然:you get the module object with a set of properties including one named default)。

有几种解决方法。

首先,您可以自己进行简单的转换 - 您需要的功能已作为模块的 default 属性 提供,因此这一行将修复它:

validate = validate.default ? validate.default : validate;

或者,您甚至可以使用 "module": "commonjs" 编译浏览器,这样 typescript 将生成工作代码,而 systemjs 将自动检测您的模块的格式。

或者最后,您仍然可以使用 "module": "system" 进行编译,但按照其输入中的预期导入 validate.js

import validate from 'validate.js';

这样你就不必对 any 进行任何转换,打字稿将为 default 属性 生成必要的访问权限,但缺点是它不起作用以这种方式导入时完全在节点中。