Сужение типа в машинописном тексте на основе перечисления в типе

скажем, например, у меня есть этот тип в машинописном тексте:

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?

• Пожалуйста, отредактируйте свой код, чтобы он был минимально воспроизводимым примером без опечаток или других проблем, за исключением той, о которой вы спрашиваете. У вас должна быть возможность протестировать это в IDE. • Предполагая, что мои исправления для этих других проблем верны, решение здесь состоит в том, чтобы создать NumberOrString тип распознаваемого объединения, а не тип объекта, где каждое свойство является независимым объединением. См. ссылку на эту игровую площадку. Это полностью решает вопрос? Если да, то я напишу ответ с объяснением. Если нет, то чего не хватает?

jcalz 30.04.2024 19:38
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
0
1
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам необходимо использовать дискриминируемое объединение : в противном случае 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, сейчас я обновил код. Спасибо!

Terry 30.04.2024 20:33

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

Переключение между информацией о карте
Как я могу показать только одно предупреждение о нескольких удалениях в angular?
Для сегмента не могут быть установлены общедоступные списки ACL с включенным BlockPublicAccess
ОШИБКА [ExceptionsHandler] Неизвестная стратегия аутентификации «jwt». Ошибка: неизвестная стратегия аутентификации «jwt»
Невозможно получить новейший токен до загрузки компонента в angular
Как исправить «Тип «void» не может быть назначен типу «Function» в VueJS?
Angular 17 – Как добавить errorStateMatcher в массив форм, но тот, который пересекает группы форм по последовательным индексам
Зачем писать возвращаемый тип защиты типа как «это (…) и это» в TypeScript?
Как временно изменить значение цветовой переменной в компоненте в Ionic 8 с помощью нового обновления цветовой палитры?
Как создать универсальный компонент формы в Next.js 14 с помощью TypeScript и формы реагирования?