TypeScript - 将模块/命名空间附加到窗口

时间:2016-05-25 07:07:06

标签: javascript module typescript typescript1.8

我使用ES2015构建了很多API和应用程序,但我还没有习惯TypeScript中的最佳实践,所以也许你可以帮助我。 我们假设我正在为商店构建API / SDK。目标是用户包含我的js文件并通过window对象访问商店及其名称空间,就像使用angular和其他lib一样。

window.shop.init();
window.shop.cart.get();
window.shop.cart.set();
window.shop.cart.clear();

在ECMAScript 2015中,我会编写我的方法,如getset,将它们导入我的主文件并扩展shop对象,最后扩展为全局对象。

// in my cart.js namespace file
export {get} from './get';

// in my shop.js
import * as cart from './cart';

global.shop = {
    cart
}

作为ES2015中命名空间的一种好方法,在具有所有模块和命名空间关键字的TypeScript中感觉有点不对。

我基本上想要在TS中实现相同的目标。我尝试过类似下面的内容,但没有成功。

module shop {
    export const cart = {...}
}

(<any>window).shop = shop;

namespace shop {
    // ...
}

(<any>window).shop = shop;

有些教程声称模块会自动附加到全局/窗口对象,但这种情况并没有发生在我身上。

我正在使用TypeScript 1.8.10。非常感谢任何帮助!

2 个答案:

答案 0 :(得分:6)

  

有些教程声称模块会自动附加到全局/窗口对象,但这种情况并没有发生在我身上。

也许是因为namespace的代码位于(ES6)模块而不是脚本中? differences between scripts and modules are detailed here

下面的代码在浏览器中创建一个全局变量shop,如果它作为脚本加载,即使用标记<script src="shop.js">(或者您可以将此文件连接到其他JavaScript文件,例如uglifyjs}。

// File shop.ts
namespace shop {
    export const cart = { /* ... */ }
}

如果您的代码是作为 ES6模块加载的(即在Webpack,SystemJS,RequireJS或其他方面的帮助下),您的解决方案是有效的:

(<any>window).shop = shop;

答案 1 :(得分:2)

@paleo的答案并不完美。 它只是抑制了商店的类型推断。

今天早上我也遇到了类似的问题。我在SO上尝试了很多“解决方案”,但它们都没有绝对产生类型错误,并且在IDE(webstorm或vscode)中启用触发类型跳转。

最后,从这里

  

https://github.com/Microsoft/TypeScript/issues/3180#issuecomment-102523512

,我找到了一个合理的解决方案附加全局变量的类型,它充当接口/类和命名空间

示例如下:

 lazy var registerButton: UIButton = {

    let rButton = UIButton(type: .system)

     rButton.frame = CGRect(x: 210, y: 600, width: 100, height: 50)

    rButton.setTitle("REGISTER", for: .normal)
    rButton.backgroundColor = UIColor.white
    rButton.translatesAutoresizingMaskIntoConstraints = false
    rButton.setTitleColor(UIColor.black, for: .normal)
    rButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)

    rButton.layer.cornerRadius = 20
    rButton.layer.borderWidth = 2

    rButton.addTarget(self, action: #selector(regSegue), for: .touchUpInside)

    return rButton
}()

// will segue for me
func regSegue(){

}

现在,上面的代码将命名空间// typings.d.ts declare interface Window { shop?: MyNamespace & typeof MyNamespace } declare interface MyNamespace { somemethod?() } declare namespace MyNamespace { // ... } 和接口MyNamespace的类型合并到全局变量MyNamespace(窗口的属性)中。