скажем, например, у меня есть этот тип в машинописном тексте:
enum NumberOrStringType {
NUMBER,
STRING,
}
type NumberOrString = {
dataType: NumberOrStringType,
data: string | number;
};
и далее в коде:
const numOrString: NumberOrString = { dataType: NumberOrStringType.NUMBER, data: 10 };
if (numOrString.dataType === NumberOrStringType.NUMBER) {
const num: number = numOrString.data;
...
} else {
const str: string = numOrString.data;
...
}
К сожалению, я получаю ошибки, говорящие, что type string | number is not assignable to type number
и type string | number is not assignable to type string
.
Я знаю, что могу просто привести num
и str
, используя as number
и as string
соответственно, но есть ли способ сообщить машинописному тексту, чтобы он определял тип data
через перечисление, или путем сужения типа с помощью оператора if?
Вам необходимо использовать дискриминируемое объединение : в противном случае Typescript не сможет сделать вывод, что когда dataType
есть NumberOrStringType.NUMBER
, то data
всегда есть number
, и наоборот для строки.
type NumberOrString = {
dataType: NumberOrStringType.NUMBER;
data: number;
} | {
dataType: NumberOrStringType.STRING;
data: string;
}
Как только вы это сделаете, ваш код должен работать:
const numOrString = { dataType: NumberOrStringType.NUMBER, data: 10 } as NumberOrString;
if (numOrString.dataType === NumberOrStringType.NUMBER) {
const num = numOrString.data;
} else {
const str = numOrString.data;
}
Пример детской площадки смотрите здесь.
@jcalz Ах, это TS определил объект как const, сейчас я обновил код. Спасибо!
• Пожалуйста, отредактируйте свой код, чтобы он был минимально воспроизводимым примером без опечаток или других проблем, за исключением той, о которой вы спрашиваете. У вас должна быть возможность протестировать это в IDE. • Предполагая, что мои исправления для этих других проблем верны, решение здесь состоит в том, чтобы создать
NumberOrString
тип распознаваемого объединения, а не тип объекта, где каждое свойство является независимым объединением. См. ссылку на эту игровую площадку. Это полностью решает вопрос? Если да, то я напишу ответ с объяснением. Если нет, то чего не хватает?