Почему перегрузка пространства имен не работает? - PullRequest
0 голосов
/ 15 октября 2018

Следующий пример пытается перегрузить пространство имен 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, но имейте в виду, что это упрощенный пример того, что я пытаюсьчтобы достичь и, как таковой, это просто минимум, который демонстрирует проблему.

1 Ответ

0 голосов
/ 15 октября 2018

Проблема в том, что константы являются значениями, а не типами.Чтобы получить тип константы, вам нужно использовать 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: Тип NA не является строкой, потому что вы использовали объявление const.Если вы используете const, выводится самый узкий из возможных типов.В данном случае это строковый литерал типа «hello».

Q: Почему 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)

...