Интерфейс машинописи со свойствами ОБА или НИ - PullRequest
0 голосов
/ 30 октября 2018

У меня есть пары ключ-значение, которые «приходят парами». Другими словами, если у меня есть одна пара ключ-значение A:B, я также хочу, чтобы у моего объекта была C:D, но она также не может иметь ни одну пару. (Подумайте message:string для одной пары и min-length:number для другой пары.) Существует ли элегантный способ сделать интерфейс, состоящий из произвольного числа таких пар?

Edit: Для пояснения я хочу разработать интерфейс для объектов, где это будет разрешено:

{
    //First pair
    message1: string;
    minLength1: number;
    //Second pair
    message2: string;
    minLength2: number;
    // ...
}

{
    //First pair omitted altogether

    //Just the second pair
    message2: string;
    minLength2: number;
}

... но там, где подобные объекты НЕ допускаются, потому что у вас есть только половина пары:

{
    //First pair
    message1: string;
    // minLength1: number; // Error †
    // ...
}

† Ошибка: если включено message1, необходимо также указать minLength1

1 Ответ

0 голосов
/ 31 октября 2018

Для данной пары свойств самое близкое приближение, которое вы можете сделать, чтобы потребовать оба свойства или ни того, ни другого, является объединением типа с обоими свойствами и типом с необязательными свойствами типа never (что предотвращает присутствие свойств со значением, отличным от undefined). Я получил идею от этого ответа . Это даст вам ошибку в правильных случаях, хотя сообщение об ошибке может быть не особенно полезным. Затем вы можете просто пересекать объединения для всех пар свойств, которые вы хотите (при условии, что у вас не более 10 пар, потому что когда TypeScript упрощает тип, он распределяет пересечения объединений, создавая объединения пересечений, что взорвать размер типа в геометрической прогрессии). Для вашего примера:

type AllOrNone<T> = T | {[K in keyof T]?: never};

type MyType = AllOrNone<{
    message1: string;
    minLength1: number;
}> & AllOrNone<{
    message2: string;
    minLength2: number;
}>;

Если вас действительно беспокоит случай undefined и вы хотите использовать универсальную функцию для проверки ваших объектов вместо записи одного типа, тогда вы можете сделать что-то вроде этого:

type CheckAllOrNone<A, T> =
    T | (keyof A & keyof T extends never ? {} : never);

type CheckMyType<A> = CheckAllOrNone<A, {
    message1: string;
    minLength1: number;
}> & CheckAllOrNone<A, {
    message2: string;
    minLength2: number;
}>;

function checkMyType<A extends CheckMyType<A>>(arg: A) {
    return arg;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...