使用变量类型作为另一个打字稿的类型

时间:2017-02-08 15:48:15

标签: typescript redux

是否可以将常量的值用作另一个的文字类型? 我的用例是Redux特有的,但也可以在其他地方使用。

我的行动定义如下:

import { APP_NAME } from 'js/commons/constants/ReduxAppName';

const MODAL_OPEN = `${APP_NAME}/MODAL/OPEN`;
const MODAL_CLOSE = `${APP_NAME}/MODAL/CLOSE`;

export const types = {
    MODAL_OPEN,
    MODAL_CLOSE,
};

现在在我的reducer中我导入了这些类型:

import { types } from './modalTypes';
import { BaseActionI } from 'js/redux/interfaces/ReduxInterfaces';

const { MODAL_OPEN, MODAL_CLOSE } = types;

我想让我的减速机类型安全。动作的有效负载可以是数字(用于结束)或JSX.Element(在打开时)。

所以我想写这样的东西:

interface ModalCloseActionI extends BaseActionI {
    type: MODAL_OPEN,
    payload: number,
}

interface ModalOpenActionI extends BaseActionI {
    type: MODAL_CLOSE
    payload: JSX.Element
}

那么我可以说我的reducer需要一个ModalOpenActionI | ModalCloseActionI

类型的Action
export const modalReducer = (state = Immutable.List<JSX.Element>(), action: ModalOpenActionI | ModalCloseActionI) => {
    const { type, payload } = action;
    switch (type) {
        case MODAL_OPEN: {
            return state.push(payload);
        }
        case MODAL_CLOSE: {
            return state.remove(payload as number);
        }
        default: {
            return state;
        }
    }
}

那么我的switch案例是类型安全的,编译器可以假设在MODAL_OPEN内有效负载实际上是JSX.Element

有没有办法在不写重复代码的情况下完成此任务?

1 个答案:

答案 0 :(得分:1)

您正在尝试将值用作类型,但不起作用 好消息是您可以使用相同的名称定义类型:

const { MODAL_OPEN, MODAL_CLOSE } = types;
type MODAL_OPEN = string;
type MODAL_CLOSE = string;

这应该有效。

修改

如果您希望类型为单个字符串文字,请执行以下操作:

interface ModalCloseActionI extends BaseActionI {
    type: "close",
    payload: number,
}

interface ModalOpenActionI extends BaseActionI {
    type: "open"
    payload: JSX.Element
}

如果字符串值不是静态的,那么你就无法做到这一点,就像你创建它们一样:

const MODAL_OPEN = `${APP_NAME}/MODAL/OPEN`;

第二次编辑

即使使用静态字符串文字,您仍需要将其声明为类型:

const { MODAL_OPEN, MODAL_CLOSE } = types;
type MODAL_OPEN = "MODAL/OPEN";
type MODAL_CLOSE = "MODAL/CLOSE";

这很烦人,因为你需要重新声明每个变量,并且你在字符串值中有重复(这可能会导致错误)。

您可以导出命名空间而不是const:

export namespace types {
    export const MODAL_OPEN = `MODAL/OPEN`;
    export type MODAL_OPEN = "MODAL/OPEN";

    export const MODAL_CLOSE = `MODAL/CLOSE`;
    export type MODAL_CLOSE = "MODAL/CLOSE";
}

然后定义在同一个地方,但你需要像这样使用它:

interface ModalCloseActionI {
    type: types.MODAL_OPEN,
    payload: number,
}

interface ModalOpenActionI {
    type: types.MODAL_CLOSE
    payload: JSX.Element
}