【问题标题】:ngrx reducer Property does not exist on typengrx reducer 属性在类型上不存在
【发布时间】:2018-08-06 03:51:49
【问题描述】:

我正在使用 TypeScript 2.7.1 和 ngrx。我的操作如下所示:

import { Action } from '@ngrx/store';


export const HEALTH_FORM_CONTENT_CHANGED = '[setupHealthForm] Content Changed';
export const HEALTH_FORM_TITLE_CHANGED = '[setupHealthForm] Title Changed';


export class SetupHealthFormContentChangedAction implements Action {
    public type: string = HEALTH_FORM_CONTENT_CHANGED;
    constructor(public payload: { content: string }) { }
}

export class SetupHealthFormTitleChangedAction implements Action {
    public type: string = HEALTH_FORM_TITLE_CHANGED;
    constructor(public payload: { title: string }) { }
}
export type Actions
    =
    SetupHealthFormContentChangedAction
    | SetupHealthFormTitleChangedAction;

我的 Reducer 看起来像这样:

import { Actions, HEALTH_FORM_TITLE_CHANGED, HEALTH_FORM_CONTENT_CHANGED } from './setup-health-form.actions';


export interface State {
    title: string;
    body: string;
}

const initialState: State = {
    title: '',
    body: ''
}

export function reducer(state: State = initialState, action: Actions): State {

    switch (action.type) {
        case HEALTH_FORM_TITLE_CHANGED: { 
            return {
                ...state,
                ...{ title: action.payload.title }
            }
        }
        case HEALTH_FORM_CONTENT_CHANGED: {
            return {
                ...state,
                ...{ body: action.payload.content }
            }
        }
        default: {
            return state;
        }
    }
}

export const body = (state: State) => state.body;
export const title = (state: State) => state.title;

但是我收到以下打字稿错误:

error TS2339: Property 'title' does not exist on type '{ content: string; } | { title: string; }'.
error TS2339: Property 'content' does not exist on type '{ content: string; } | { title: string; }'.

我发现解决此问题的唯一方法是导出带有 any 类型有效负载的操作。如何正确解决此问题以保留我的输入?

【问题讨论】:

    标签: angular typescript ngrx


    【解决方案1】:

    要使用可区分的联合类型及其switch 类型保护行为,type 的类型必须是字符串文字类型(基本上是只能是单个值的字符串类型)。您的type 字段是string,即使您为其分配了一个常量。发生这种情况是因为 typescript 假定您将要改变该字段,因此将其键入为 string。如果您将其标记为 readonly 并删除显式的 string 类型,则该字段将使用常量的类型(它是字符串文字类型)进行键入,并且您的 switch 将正确进行类型检查:

    export class SetupHealthFormContentChangedAction  {
        public readonly type = HEALTH_FORM_CONTENT_CHANGED;
        constructor(public payload: { content: string }) { }
    }
    
    export class SetupHealthFormTitleChangedAction implements Action {
        public  readonly type = HEALTH_FORM_TITLE_CHANGED
        constructor(public payload: { title: string }) { }
    

    Playground sample code

    【讨论】:

    • 我已根据您的示例添加只读但问题尚未解决。
    • @that_guy 嗯。我已经安装了 2.8,让我检查一下 2.7,我会尽快更新答案
    • @that_guy 我在操场上检查过,它也适用于 2.7。您是否从 type 中删除了显式类型?应该是 public readonly type = HEALTH_FORM_TITLE_CHANGED 而不是 public readonly type : string = HEALTH_FORM_TITLE_CHANGED
    • 就是这样!我的错。谢谢!
    【解决方案2】:

    添加到Titian 的现有答案中,就我而言,如果type 定义是一个字符串被连接,则会发生错误(这是我的IDE 设置的行为,称为硬换行以自动中断,如果该行是太长)。 您需要确保 type 是一个具体的单个 const 字符串。

    不工作

    export const GET_SYSTEM_CLOSING_REPORT_OF_PROJECT_MANAGER = '[MonthClosingReportActions] Get System Closing Reports of' +
        ' project manager';
    export class GetSystemClosingReportOfProjectManagerAction implements Action {
        readonly type = GET_SYSTEM_CLOSING_REPORT_OF_PROJECT_MANAGER;
        constructor(public payload: string) {}
    }
    

    工作

    export const GET_SYSTEM_CLOSING_REPORT_OF_PROJECT_MANAGER = '[MonthClosingReportActions] Get System Closing Reports of project manager';
    export class GetSystemClosingReportOfProjectManagerAction implements Action {
        readonly type = GET_SYSTEM_CLOSING_REPORT_OF_PROJECT_MANAGER;
        constructor(public payload: string) {}
    }
    

    【讨论】:

      猜你喜欢
      • 2018-04-25
      • 1970-01-01
      • 1970-01-01
      • 2020-06-24
      • 2020-05-22
      • 2021-01-09
      • 2019-06-11
      • 2021-07-10
      相关资源
      最近更新 更多