2016-11-08 59 views
3

我試圖在客戶端和服務器中使用現有的js庫(validate.js)。導入出錯了systemjs

我使用npm安裝了它,並且一切都爲服務器和客戶端編譯。
在服務器中使用它時效果很好,但是當我在瀏覽器中執行它時會引發錯誤。

同樣的文件在這兩種情況下使用:

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

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

validate是斷言any監守否則我得到:

TS2349:無法調用其類型缺乏調用簽名的表達式。

我使用的是.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; 
} 

模塊僅導出功能,並且效果很好的服務器,但在客戶端調用這個函數,我得到的時候:

"use strict"; 
const validate = require("validate.js"); 
... 
Uncaught TypeError: validate is not a function(…) 

該代碼是使用靶標commonjs服務器編譯

而且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() 
    ... 

任何想法是怎麼回事,爲什麼它在瀏覽器中的行爲這種方式?

+1

請參閱CommonJS上本段的最後一句:https://github.com/systemjs/systemjs/blob/master/docs/module-formats.md#commonjs。 SystemJS不會像NodeJS一樣加載CommonJS模塊。有'@節點',但我沒有這種黑魔法的個人經驗。 – martin

+0

@馬丁很好,是不是那個花花公子。我特別喜歡:「這應該只在絕對必要時才使用,因爲它會阻止代碼的通用性,並且只能與NodeJS兼容」。那麼現在我也被迫使用'jspm'? –

+0

我從來沒有使用過這個選項,我只記得是看到它提到那裏... – martin

回答

3

當你"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屬性,但缺點是它在導入該節點時根本無法在節點中工作。

+0

謝謝!我結束了使用'validate.default'選項。將它導入就像你給出的最後一個選項一樣好,但不幸的是,需要在瀏覽器和節點中運行相同的代碼。 –