Тип объединения для аналогичной структуры интерфейсов - PullRequest
0 голосов
/ 13 февраля 2019

Как реализовать объединение типов с включенным флагом typeof для переменных в конфигурации для набора текста

Есть площадка TS

Удаление определения типа в первой строке работает нормально, но tslint генерирует ошибку для него.Примеры в http://www.typescriptlang.org/docs/handbook/advanced-types.html с (сущностью) не помогли.

const TYPE_A: string = 'TYPE_A'; // <- type difinition here breaks line 19
interface Action_A {
    type: typeof TYPE_A;
    payload: {
        entities: [];
    }
}

const TYPE_B = 'TYPE_B';
interface Action_B {
    type: typeof TYPE_B;
    payload: {
        id: number
    }
} 

const shouldBeReducer = (action: Action_A | Action_B) => {
    if (action.type === TYPE_A) {
        return action.payload.entites // <- entities field is not defined
    }
}

определение типа в редукторе должно работать корректно, но отображается исключение

1 Ответ

0 голосов
/ 13 февраля 2019

Используйте класс вместо интерфейса и instanceof type guard.

const TYPEA: number = 1; // type difinition here breaks line 19
class ActionA {
    type: typeof TYPEA;
    payload: {
        entities: [];
    }
}

const TYPEB = 2;
class ActionB {
    type: typeof TYPEB;
    payload: {
        id: number
    }
} 

const reducer = (action: ActionA | ActionB) => {
    if (action instanceof ActionB) {
        action.payload.id // OK
    }
}

Playground

Однако если вы хотите сохранить интерфейсы, вам следует изменить свой кодна это:

const TYPEA = 1 as 1; // type difinition here breaks line 19
interface ActionA {
    type: 1;
    payload: {
        entities: [];
    }
}

const TYPEB = 2 as 2;
interface ActionB {
    type: typeof TYPEB;
    payload: {
        id: number
    }
} 

const reducer = (action: ActionA | ActionB) => {
    if (action.type === TYPEB) {
        action.payload.id // OK
    }
}

Детская площадка

Проблема заключалась в том, что TYPEA и TYPEB были выведены как number, а не как числовые литералы (1, 2).

...