Можно ли объединить глобальную область видимости в TypeScript?

Если вы создадите тип объединения, а затем используете оператор if для идентификации его типа, TypeScript позволит вам использовать свойства и функции, специфичные для этого типа:

type A = {
    type: "A",
    func(): void
};

type B = {
    type: "B"
};

type Union = A | B;

const test: Union = ...;

test.func(); // Error: func does not exist on type B

if (test.type === "A")
    test.func(); // Works fine

Можно ли сделать это объединение глобально, объединив две области видимости? Что-то вроде этого было бы очень хорошо:

declare global {
    environment: "A",
    funcA(): void
} | {
    environment: "B",
    funcB(): void
}

funcA(); // Doesn't work (environment could be B, and B doesn't have funcA)

if (environment === "A")
    funcA(); // Works (environment is A)
else
    funcB(); // Works (environment is B)

Я пытался найти это, но не смог найти ничего, что соответствовало бы моим потребностям. Есть ли какой-либо конкретный синтаксис или какие-либо обходные пути?


1
57
1

Ответ:

Решено

Один из подходов — использовать деструктурированный дискриминируемый союз , где вы назначаете переменные environment, funcA и funcB как деструктурированные из объекта типа дискриминируемого союза. Вот пример использования кортежа:

declare const
    [environment, funcA, funcB]:
        ["A", () => void, undefined] |
        ["B", undefined, () => void];

funcA(); // error!
if (environment === "A") {
    funcA(); // okay
} else {
    funcB(); // okay
}

Это работает, потому что environment считается дискриминантным свойством дискриминируемого союза. Когда вы отметите это, то funcA и funcB соответственно сузятся.

Детская площадка, ссылка на код