Typescript 可以导入 Webpack UMD 吗?

Posted

技术标签:

【中文标题】Typescript 可以导入 Webpack UMD 吗?【英文标题】:Can Typescript import Webpack UMD? 【发布时间】:2016-06-14 19:26:30 【问题描述】:

使用 TypeScript,有没有办法import 一个已经被 webpack UMD(通用模块定义)包装的模块?例如:

npm install knockback

.js 文件 (node_modules/knockback/knockback.js) 开头如下:

(function webpackUniversalModuleDefinition(root, factory) 
    if(typeof exports === 'object' && typeof module === 'object')
        module.exports = factory(require("knockout"), require("backbone"), ....
    else if(typeof define === 'function' && define.amd)
        define(["knockout", "backbone", "underscore"], function webpackLoadOptionalExternalModuleAmd( ....
        );
    else if(typeof exports === 'object')
        exports["kb"] = factory(require("knockout"), require("backbone"), require("underscore"), (function ....
    else
        root["kb"] = factory(root["ko"], root["Backbone"], root["_"], root["jQuery"]);

当我尝试将其导入 .ts 文件时,tsc 会产生错误:

import * as k from 'knockback/knockback';

TS2307: Build: Cannot find module 'knockback/knockback'.

除了编辑 knockback.js 文件之外,我还能做些什么来说服 tsc 导入这个 .js?我正在使用 Typescript 1.8。

【问题讨论】:

【参考方案1】:

当我尝试将其导入 .ts 文件时,tsc 会产生错误:

你可以很容易地使用类型定义文件

文件knockback.d.ts

declare module 'knockback/knockback' 
    var foo: any;
    export = foo;

【讨论】:

【参考方案2】:

仅供参考,对于最终在这里尝试通过 Typescript 使用 knockback.js 的其他任何人,DefinitelyTyped 提供了一个预先存在的 knockback.d.ts 文件。但是,现有的 .d.ts 不包含 export,因此无法与外部模块一起使用。根据basarat的回答,我修改了.d.ts文件如下:

1) 在末尾添加以下内容:

declare module "knockback" 
    export = Knockback;

2) 从末尾删除declare var kb: Knockback.Static

3) 移除 interface Static extends Utils 包装器并将 Static 接口内的所有内容移动到命名空间范围。示例:

旧:

interface Static extends Utils 
    ViewModel;
    CollectionObservable;
    collectionObservable(model?: Backbone.Collection<Backbone.Model>, options?: CollectionOptions): CollectionObservable;
    observable(
        /** the model to observe (can be null) */
        model: Backbone.Model,
        /** the create options. String is a single attribute name, Array is an array of attribute names. */
        options: IObservableOptions,
        /** the viewModel */
        vm?: ViewModel): KnockoutObservable<any>;
    ...

新:

    function collectionObservable(model?: Backbone.Collection<Backbone.Model>, options?: CollectionOptions): CollectionObservable;
    function observable(
        /** the model to observe (can be null) */
        model: Backbone.Model,
        /** the create options. String is a single attribute name, Array is an array of attribute names. */
        options: IObservableOptions,
        /** the viewModel */
        vm?: ViewModel): KnockoutObservable<any>;
    ...

进行这些更改后,用法如下所示:

import * as kb from 'knockback';

class MyViewModel extends kb.ViewModel 
    public name: KnockoutObservable<string>;

    constructor(model: Backbone.Model) 
        super();

        this.name = kb.observable(model, "name");
    


var model = new Backbone.Model( name: "Hello World" );
var viewModel = new MyViewModel(model);

kb.applyBindings(viewModel, $("#kb_observable")[0]);

【讨论】:

以上是关于Typescript 可以导入 Webpack UMD 吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用 WebPack + TypeScript 定义导入的外部模块

Webpack / typescript 要求有效,但导入无效

Webpack:“通常”和作为原始字符串导入 TypeScript 模块

如何防止 jquery 使用 webpack 和 typescript 导入两次?

带有 es6 导入的 Module.exports 用于 typescript 中的 webpack.config.ts

typescript 动态导入与 tsconfig.json 中的 webpack.config 冲突?