首页 > 解决方案 > 接口结构相似的联合类型

问题描述

如何在打字稿配置中为变量实现带有启用 typeof 标志的联合类型

TS游乐场在那里

在第一行中删除类型定义可以正常工作,但 tslint 会为它生成错误。http://www.typescriptlang.org/docs/handbook/advanced-types.html中带有 (entity) 的示例没有帮助。

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
    }
}

reducer 中的类型定义应该可以正常工作,但会显示异常

标签: typescriptreducersunion-types

解决方案


使用类而不是接口和instanceof类型保护。

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
    }
}

操场

但是,如果要保留接口,则应将代码更改为:

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而不是数字文字(12)。


推荐阅读