Как условно установить свойство TypeScript на основе другого вложенного свойства?

Технопарк Нобель
Технопарк Нобель
  • Сообщений: 9
  • Последний визит: 20 января 2025 в 01:51
Как условно установить свойство TypeScript на основе другого вложенного свойства?

У меня есть следующие типы:
type Settings = {
    enableAdvancedFeature?: boolean;
};
 
type Options = {
    settings?: Settings;
    enforceAdvancedOrder?: boolean;
};

Я хочу сделать enforceAdvancedOrder свойство является логическим значением только тогда, когда settings.enableAdvancedFeature является true.

Если settings.enableAdvancedFeature является false или undefined, затем enforceAdvancedOrder должно быть undefined.

Вот пример желаемого поведения:
const validOption1: Options = {
    settings: { enableAdvancedFeature: true },
    enforceAdvancedOrder: true,
};
 
const validOption2: Options = {
    settings: { enableAdvancedFeature: false },
    enforceAdvancedOrder: undefined, // enforceAdvancedOrder should be undefined
};
 
const invalidOption: Options = {
    settings: { enableAdvancedFeature: false },
    enforceAdvancedOrder: true, // This should cause a TypeScript error
};<code>
Я попытался определить условный тип для параметров, но не смог понять, как обеспечить эту зависимость между вложенными свойствами.
 
Как я могу определить тип Options, чтобы добиться такого поведения, сохраняя при этом его безопасность? Любые предложения будут очень признательны!
Владимир Соколов
Владимир Соколов
  • Сообщений: 14
  • Последний визит: 20 января 2025 в 01:48
Просто так:
type ConditionalOption =
    | { enforceAdvancedOrder?: boolean, settings?: { enableAdvancedFeature?: true } }
    | { enforceAdvancedOrder?: undefined, settings?: { enableAdvancedFeature?: false | undefined } }

Примеры:
let a: ConditionalOption = {
    settings: {
        enableAdvancedFeature: true
    },
    enforceAdvancedOrder: true
} // okay
 
let b: ConditionalOption = {
    settings: {
        enableAdvancedFeature: false
    },
    enforceAdvancedOrder: true
} // throws error
 
let c: ConditionalOption = {
    settings: {
        enableAdvancedFeature: false
    },
    enforceAdvancedOrder: undefined
} // okay
Автотрейд
Автотрейд
  • Сообщений: 14
  • Последний визит: 20 января 2025 в 01:49
Вы можете использовать тип объединения, который позволяет enforceAdvancedOrder быть логическим значением, если enableAdvancedFeatures установлено на true и в противном случае требует, чтобы enforceAdvancedOrder является неопределенным.

Вот как:
type Options = ({
    settings?: Settings<true>;
    enforceAdvancedOrder?: boolean;
} | {
    settings?: Settings<false | undefined>;
    enforceAdvancedOrder?: never;
});
 
type Settings<B extends boolean | undefined = boolean> = B extends undefined ? {
    enableAdvancedFeature?: B;
} : {
    enableAdvancedFeature: B;
};

Вот несколько образцов для проверки:
const validOption1: Options = {
    settings: { enableAdvancedFeature: true },
    enforceAdvancedOrder: true,
};
 
const validOption2: Options = {
    settings: { enableAdvancedFeature: false },
    enforceAdvancedOrder: undefined, // enforceAdvancedOrder should be undefined
};
 
const validOption3: Options = {
    settings: {},
    enforceAdvancedOrder: undefined, // enforceAdvancedOrder should be undefined
};
 
const invalidOption: Options = {
    settings: { enableAdvancedFeature: false },
    enforceAdvancedOrder: true, // This should cause a TypeScript error
};
 
const invalidOption2: Options = {
    settings: {},
    enforceAdvancedOrder: true, // This should cause a TypeScript error
};
Авторизуйтесь, чтобы писать на форуме.

Заявка на услуги DST

Наш специалист свяжется с вами, обсудит оптимальную стратегию сотрудничества,
поможет сформировать бизнес требования и рассчитает стоимость услуг.

Адрес

Ижевск, ул. Воткинское шоссе, д. 170 Е, Технопарк Нобель, офис 1117

8 495 1985800
Заказать звонок

Режим работы: Пн-Пт 10:00-19:00

info@dstglobal.ru

Задать вопрос по почте

Укажите ваше имя
Укажите ваше email
Укажите ваше телефон