为什么名称空间重载不起作用?

时间:2018-10-15 16:14:38

标签: typescript namespaces export overloading

下一个示例试图重载名称空间N,但不幸的是,编译器抱怨AB都不是它的导出成员。

namespace N
{
    export const A = 'hello';
    export const B = 'world';
}

type N = N.A | N.B;

const a: N = N.A;
const b: N = N.B;

console.log(a, b);

尽管如此,运行编译后的代码仍会提供以下预期输出:

hello world

因此,问题显然是:为什么编译器会抱怨?抱怨是否合理?

  

注意 1 :我正在使用的编译器版本为3.1.1

  

注意 2 :我知道上面的内容可以写成enum,但是请记住,这是我所简化的示例我试图实现这一目标,因此这仅仅是演示问题的最低要求。

1 个答案:

答案 0 :(得分:1)

问题在于常量是值,而不是类型。要获取常量的类型,您需要使用typeof

namespace N
{
    export const A = 'hello';
    export const B = 'world';
}

type N = typeof N.A | typeof N.B;

const a: N = N.A;
const b: N = N.B;

console.log(a, b);

注意:类型和名称空间实际上并没有任何共同之处,它们是不同的符号,只是碰巧共享相同的名称。没有合并行为(例如接口和类会存在合并行为)

修改

问:为什么N.A的类型不是string

A:N.A的类型不是字符串,因为您使用了const声明。如果使用const,则推断可能的最窄类型。在这种情况下,这是字符串文字类型“ hello”。

问:为什么type N = "hello" | "world"起作用但type N = N.A | N.B;不起作用?

A:Typescript允许将字符串文字用作类型,如上所述。但是它们是类型。您不能在表达式中使用它们,只能在类型注释中使用N(即let a = N不能使用)。另一方面,变量是一个值。您可以在表达式中使用它,而不能在类型注释中使用它(例如let o:N.A是错误)。要获取变量的类型,您需要typeof(这样可以正常工作:let o: typeof N.A