You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript Discriminated Union报错:属性在类型上不存在(Reducer场景)

解决Reducer中Discriminated Union类型的payload属性不存在错误

问题原因

提前执行const { type, payload } = action解构后,TypeScript无法再关联type与payload的类型绑定关系——二者成为独立变量后,payload始终是两个action payload的联合类型,导致在case分支中访问专属属性时触发类型检查错误。

解决方案

方案1:避免提前解构(推荐)

直接在switch分支中使用action.type和action.payload,让TypeScript自动收窄每个分支的payload具体类型:

interface AuthenticatedUserState {
    user?: any
    isAdmin?: boolean
    isRegistered?: boolean
    err?: any
    isError?: boolean
    isSignedOut?: boolean
    authorizationData?: any
}

const INITIAL_STATE: AuthenticatedUserState = {
    user: null,
    isError: false,
    err: null,
    isSignedOut: false
}

interface AUTHENTICATED_USER_ACTION {
    type: 'authentication/AUTHENTICATED_USER'
    payload: {
        authenticatedUser: any
        isAdmin: boolean
    }
}

interface REGISTER_USER_ACTION {
    type: 'authentication/REGISTER_USER'
    payload: {
        isRegistered: boolean
        err: any
    }
}

const AUTHENTICATED_USER = 'authentication/AUTHENTICATED_USER'
const REGISTER_USER = 'authentication/REGISTER_USER'

type ACTION = AUTHENTICATED_USER_ACTION | REGISTER_USER_ACTION

const authenticatedUserReducer = (
    state: AuthenticatedUserState = INITIAL_STATE,
    action: ACTION
): AuthenticatedUserState => {
    switch (action.type) {
        case AUTHENTICATED_USER:
            return {
                ...state,
                user: action.payload.authenticatedUser,
                isAdmin: action.payload.isAdmin
            }
        case REGISTER_USER:
            return {
                ...state,
                isRegistered: action.payload.isRegistered,
                err: action.payload.err
            }
        default:
            return state
    }
}

方案2:使用类型断言(按需选择)

如果业务场景必须提前解构,可以在每个case分支中给payload做类型断言,明确当前分支的payload类型:

const authenticatedUserReducer = (
    state: AuthenticatedUserState = INITIAL_STATE,
    action: ACTION
): AuthenticatedUserState => {
    const { type, payload } = action
    switch (type) {
        case AUTHENTICATED_USER:
            const authPayload = payload as AUTHENTICATED_USER_ACTION['payload']
            return {
                ...state,
                user: authPayload.authenticatedUser,
                isAdmin: authPayload.isAdmin
            }
        case REGISTER_USER:
            const registerPayload = payload as REGISTER_USER_ACTION['payload']
            return {
                ...state,
                isRegistered: registerPayload.isRegistered,
                err: registerPayload.err
            }
        default:
            return state
    }
}

内容的提问来源于stack exchange,提问作者LogiStack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 21:50:34