Typescript coditional интерфейс - PullRequest
1 голос
/ 30 апреля 2020

У меня есть 2 интерфейса

interface i1 {
    x: number;
}

interface i2  {
    x: number;
    y: number;
    z: number
}

// ok
const o: i1 = {
    x: 1,
}

// ok
const o: i2 = {
    x: 1,
    y: 2,
    z: 3
}

Я хочу указать, что если мой объект имеет поле y, оно должно иметь также поле z

Я пытаюсь его решить таким образом

    // expected error but everything is "fine"
    const o: i1 | i2 = {
        x: 1,
        y: 2,
    }

Если я прав { x: number, y: number } не должен совпадать ни с одним из i1 или i2.

Какой правильный подход для этого? Спасибо, ребята.

1 Ответ

2 голосов
/ 30 апреля 2020

Вы должны сделать свой союз из i1 | i2 эксклюзивным. Есть два способа сделать это.

Вручную

Это гарантирует, что y и z никогда не могут существовать на i1.

interface i1 {
  x: number;
  y?: never;
  z?: never;
}

Одно только это изменение даст нам желаемую ошибку.

Используя помощника

Мы можем создать помощника, который делает то же самое, но может использоваться повторно .

type DistributedKeyOf<T> =
T extends any
    ? keyof T
    : never;


type CreateExclusiveUnion<T, U = T> =
T extends any
    ? T & Partial<Record<Exclude<DistributedKeyOf<U>, keyof T>, never>>
    : never;

type ExclusiveUnion<T> = CreateExclusiveUnion<T>;

Использование:

const oa: ExclusiveUnion<i1 | i2> = {
    x: 1,
    y: 2,
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...