【问题标题】:Use type of variable as type of another typescript使用变量类型作为另一个打字稿的类型
【发布时间】:2017-02-09 16:48:01
【问题描述】:

是否可以将常量的值用作另一个常量的字面量类型? 我的用例是 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 case 是类型安全的,编译器可以假设在 MODAL_OPEN 内部,有效负载实际上是 JSX.Element

有没有办法在不编写大量重复代码的情况下实现这一点?

【问题讨论】:

    标签: typescript redux


    【解决方案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
    }
    

    【讨论】:

    • 对不起,如果我的问题不清楚。我希望类型是字符串文字。但如果我将变量设为静态,它也不起作用。有没有办法做到这一点?
    • 非常感谢。把所有的东西都写两次是很不错的,而且 switch 语句在类型保护方面效果不佳,但它确实有效。非常感谢
    猜你喜欢
    • 2021-04-19
    • 1970-01-01
    • 2021-06-17
    • 2020-10-27
    • 1970-01-01
    • 2020-06-29
    • 2022-01-07
    • 2021-11-19
    • 1970-01-01
    相关资源
    最近更新 更多