导入模块会破坏带有属性的本地类型,类型上不存在

时间:2018-08-26 11:04:40

标签: typescript

我有一个名为CarType的枚举,它在一个名为CarType.ts的文件中。代码如下:

namespace MyProduct.Search {
    export enum CarType {
        Sedan = 0,
        Wagon = 1,
        Cabrio = 2,
        /* etc */
    }
}

在同一目录中名为SearchMain.ts的另一个文件中,我有以下代码:

/// <reference path="../../d.ts/jquery.d.ts" />
/// <reference path="../../d.ts/knockout.d.ts" />
/// <reference path="../../d.ts/fullcalendar.d.ts" />
namespace MyProduct.Search {
    export module SearchMain {
        export function Init() {

             /* snip */
             let type: CarType = CarType.Sedan;

        }
        /* snip */
    }
}

在我尝试导入完整日历类型之前,以上方法工作正常。我在/// reference行下方添加以下行

import { EventObjectInput } from 'fullcalendar/src/types/input-types';

CarType变得不可用。 Intellisense错误为Property 'CarType' does not exist on type 'typeof Search'

如何使用完整日历中的EventObjectInput和代码?

1 个答案:

答案 0 :(得分:1)

这是一个令人困惑的问题:

Typescript具有内部模块或名称空间,由关键字namespacemodule标识。 这两个关键字的含义相同。这是令人困惑的部分,因为module实际上并不意味着JS模块。 命名空间基本上只是用于实现“显示模块模式”的语法糖。在我们在javascript中使用实际模块之前,我们通常会做这种类型的事情,并且不鼓励使用它。

我建议您查看Typescript游乐场,以了解namespace关键字在转换为javascript时的实际作用。 (example)

基本上,namespace只是创建一个对象,您可以在其中控制在对象外部看到的内容。另一个属性是,如果您有两个名称空间声明,并且在同一作用域上具有相同的名称,则合并这些声明。 但最终,它只是在已编译的javascript中作为另一个变量实现。

Typescript还具有“真实”模块,也称为外部模块。实际模块意味着它们是隔离的,您需要某种机制才能在运行时加载它们。如果您的代码打算在node.js中运行,则可以是webpack或browserify,也可以是require函数,可以是reuqire.js库,但是您需要一些东西。

任何具有顶级 exportimport语句的文件都是模块。 (在名称空间内导出不是顶级!)

因此,我们有两个选择: 1.文件不是模块。 2.文件是一个模块。

如果文件不是模块,则文件中声明的每个变量/类型都在全局范围内声明。

如果文件是模块,则每个变量/类型的作用域仅限于该文件。

因此,一旦添加: import { EventObjectInput } from 'fullcalendar/src/types/input-types'; 您将SearchMain.ts转换为外部模块。现在MyProduct.Search中的命名空间SearchMain.ts已被隔离,其定义范围不同于CarType.ts中定义的命名空间。这样您就会出错。


TL; DR-您可以做什么?

将内部模块和外部模块混合在一起很烦人。选一个。 强烈建议仅使用外部模块。不要使用名称空间,只需导入和导出语句即可。迁移代码可能要花一些时间,但这是值得的。

另一个选择是继续使用namespace。请勿import EventObjectInput。使它在其他名称空间上可用。但是同样,不建议这样做。


for more info from Typescript documentation

related stack overflow answer