繁体   English   中英

没有强制转换的 TypeScript 窄枚举类型 (Redux)

[英]TypeScript Narrow Enum Type without Casting (Redux)

我想更有效地输入我的 redux 操作。 目前,我在类Actions声明我的Actions并明确缩小操作类型的范围。 这样打字稿将缩小减速器中action的类型,我可以在那里看到哪种类型的action.payload哪个好。

但我想摆脱显式转换<ActionTypes.INCREMENT_BY_ONE>ActionTypes.INCREMENT_BY_ONE 它可以做得更通用/更容易/更短吗?

export enum ActionTypes {
    INCREMENT_BY_ONE = 'INCREMENT_BY_ONE',
    INCREMENT_BY_MULTIPLE = 'INCREMENT_BY_MULTIPLE',
}

class Actions {
    incrementByOne() {
        return {
            type: <ActionTypes.INCREMENT_BY_ONE>ActionTypes.INCREMENT_BY_ONE,
        };
    }
    incrementByMultiple(multiple: number) {
        return {
            type: <ActionTypes.INCREMENT_BY_MULTIPLE>ActionTypes.INCREMENT_BY_MULTIPLE,
            payload: multiple,
        };
    }
}

type ValueOf<T> = T[keyof T];
export type KnownAction = ReturnType<ValueOf<Actions>>;

function reducer(state, action: KnownAction) {
    switch(action.type) {
        case ActionTypes.INCREMENT_BY_ONE:
            // Property 'payload' does not exist on type { type ActionTypes.INCREMENT_BY_ONE; }.
            const a = action.payload; 
            break;
        case ActionTypes.INCREMENT_BY_MULTIPLE:
            // payload: number
            const b = action.payload;
            break;
    }
}

https://stackblitz.com/edit/typescript-nngwzy

你必须告诉 TypeScript 尽可能缩小类型。 您只能明确地执行此操作 - 但是有一种很好的方法可以告诉 TypeScript 执行此操作。

class Actions {
    incrementByOne() {
        return {
            // Typecast using const, this tells TypeScript to narrow down the type to the most specific one, which is ActionTypes.INCREMENT_BY_ONE
            type: <const>ActionTypes.INCREMENT_BY_ONE, 
        };
    }
    incrementByMultiple(multiple: number) {
        return {
            type: ActionTypes.INCREMENT_BY_MULTIPLE as const, // Alternatively using 'as' syntax
            payload: multiple,
        };
    }
}

或者,您可以将整个 Action 标记为 const - 好处是所有属性也将标记为只读。 这是你通常想要的 Action。

class Actions {
    incrementByOne() {
        return <const> {
            type: ActionTypes.INCREMENT_BY_ONE, 
        };
    }
    incrementByMultiple(multiple: number) {
        return {
            type: ActionTypes.INCREMENT_BY_MULTIPLE,
            payload: multiple,
        } as const; // Alternatively using 'as' syntax
    }
}

这里是Stackblitz。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM