Предоставить один из типов объектов в машинописи

Если я наберу следующее:

interface A {
    x: number
}
interface B {
    y: number
}

type Z = A | B;

// here it allows me to create a variable of type Z with both members of type A and B.
let z: Z = {
    x: 5,
    y: 6,
}

Я не могу гарантировать, что объект типа Z содержит все члены A, но не содержит членов B (или наоборот). Возможно ли это вообще с TypeScript? После долгих исследований я склоняюсь к ответу "нет", но я не уверен.

1 ответ

Решение

По умолчанию союзы объединяют все варианты, предлагаемые в, в один, но есть два варианта для вас. То, что вы хотите точно, не доступно в TypeScript, но есть похожие проблемы в списке проекта TS (статус: "открыт" в настоящее время), а также два хороших обходных пути.

Один вариант недоступен: в настоящее время нет точных типов в TypeScript (в отличие от Flow). Есть выпуск TS 12936 "Точные типы", который сейчас все еще открыт.

В списке открытых вопросов TS есть еще одна проблема / предложение, в которой точно задается вопрос: # 14094 "Предложение: разрешить монопольное объединение с использованием логического или (^) оператора между типами"


Вы можете использовать эти обходные пути:

# 1

В TypeScript, а также в Flow вы можете использовать теговые типы для создания объединения XOR вместо OR.

interface A {
    kind: 'A',
    x: number
}
interface B {
    kind: 'B',
    y: number
}

type Z = A | B;

// here it DOES NOT allow to create a variable of type Z with both members of type A and B.
let z: Z = {
    kind: 'A',
    x: 5
    // y: 6 will produce an error
}


# 2

Второй вариант - установить все свойства для всех типов, но установить те, которые не должны существовать, undefined:

interface A {
    x: number,
    y?: undefined
}
interface B {
    x?: undefined,
    y: number
}

type Z = A | B;

let z: Z = {
    y: 5
    // y: 6 will produce an error
}


Напомним, что в системе типов Facebook Facebook вы можете решить эту проблему, используя несвязанное объединение (XOR) вместо простого объединения (ИЛИ), или используя точные типы объектов, или как для TS выше, установив нежелательное свойство равным undefined, Я сделал демо Flow с вашим примером (ссылка). В этом случае код для потока такой же, как и для TS.

Другие вопросы по тегам