下一个示例试图重载名称空间N
,但不幸的是,编译器抱怨A
和B
都不是它的导出成员。
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
,但是请记住,这是我所简化的示例我试图实现这一目标,因此这仅仅是演示问题的最低要求。
答案 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
)