首页 > 解决方案 > 打字稿迁移:带有多个对象的Javascript“命名空间”

问题描述

我正在将一些旧的 js 迁移到 ts。该文件的格式为(为清楚起见省略了功能实现):

// component.js
const Component = {}; // 'namespace' for components
Component.Base = function() {}
Component.A = function() {} // extends Base
Component.A.prototype.doStuffA = function() {}
Component.B = function() {} // extends Base
Component.B.prototype.doStuffB = function() {}
Component.C = function() {} // extends Base
// ... 100 other components, 2000 lines of code
export default Component;

在 js 中,要使用该文件,我可以这样做:

import Component from './component';
// 1. Instantiate one component
const compA = new Component.A();
// 2. or create multiple components 
const threeComps = ['A', 'B', 'C'].map(name => new Component[name]() );

但在 ts 中,我什至无法实例化一个组件:

import Component from './component';
const compA: Component.A = new Component.A();
// tsc Cannot find namespace 'Component'

问题:将 component.js 转换为有效打字稿的(快速)方法是什么,最好保持尽可能多的类型检查可用,以便

const compA: Component.A = new Component.B()

将被编译器标记为错误。

我尝试将以下内容附加到文件末尾:

namespace Component {
    interface A {};
    interface B {};
    interface C {};
}

这似乎可以编译成正确的 javascript,但我必须将所有属性添加到接口中。看起来很乏味并且违反了 DRY 原则。

标签: javascripttypescript

解决方案


If you are going to migrate to TypeScript, you could immediately take advantage of the class syntax in your component.ts file:

export class Base {

}

export class A {
    doStuffA() {}
}

export class B {
    doStuffB() {}
}

export class C extends Base {

}

You can consume it using an import alias:

import * as Component from './component';

const a = new Component.A();

Or you can be selective with what you import:

import { A } from './component';

const a = new A();

Export Default / Modules Mixed With Namespaces

On the whole, the experts are saying that export default is a bad thing and that you shouldn't mix modules and namespaces.

You can do it, if you feel you must. here is the example with a namespace / default:

namespace Component {
    export class Base {

    }

    export class A {
        doStuffA() {}
    }

    export class B {
        doStuffB() {}
    }

    export class C extends Base {

    }
}

export default Component;

And the use:

import Component from './component';

const a = new Component.A();

推荐阅读