angular – ngrx有效负载在reducer动作中没有编译
我正在尝试将我的角度2应用程序迁移到角度4和ngrx 4.
我正在处理一个奇怪的打字稿编译问题,这是我在此次更新之前没有的.我在离线环境中工作,所以我不能在这里分享确切的代码. 我在网上找了问题,我能找到的最接近的是这个问题: 我不能把确切的代码解决这里,但我完全基于ngrx示例我的代码 让我们看一下书籍缩减器和书籍动作的例子 我的代码基本相同,当我尝试从操作中获取有效负载时,每个reducer情况(在switch情况下)都会发生错误, Type 'string | Book | Book[]' is not assignable to type 'Book'. Type 'string' is not assignable to type 'Book'. (在我的代码中,而不是Book我有不同的类,但它几乎相同的想法) 现在我通过从A |中转换动作类型来解决错误B |乙 我使用的版本: 更新: 任务reducer.ts: import * as MissionActionsFile from "./mission-actions"; export type State = .... // doesnt matter const initialState: State = // doesnt matter as well export function reducer(state: State = initialState,action: MissionActionsFile.Actions): State { switch(action.type) { case MissionActionsFile.ADD_SUCCESS: { const mission: Mission = action.payload; // This line generates the // following error: // Type 'string | number | Mission | MissionRealTime | ...' is not // assignable // to type 'Mission'. Type 'string' is not assignable to type 'Mission' return {}; // This doesnt matter too } // There are more cases and a deafult one,but that doesn't matter } } 任务actions.ts: // I will only give the actual action defenition for AddSuccess and for AddFailed since we are using AddSuccess in the example and // addFailed is an example where the payload type is string,which according to the error is the problem,though // there are more action types and other payload types with other classes as the quoted error implies. export const ADD_SUCCESS: string = "[Mission] AddSuccess"; export const ADD_FAILED: string = "[Mission] AddFailed"; export class AddSuccessAction implements Action { public readonly type: string = ADD_SUCCESS; constructor(public payload: Mission) {} } export class AddFailedAction implements Action { public readonly type:string = ADD_FAILED; constructor(public payload: string) {} } // More actions are defined here but im not gonna copy all ... export type Actions = AddSuccessAction | AddFailedAction; 总而言之,我确实看到为什么对于打字稿,认为动作有效负载类型可能是字符串|使命| …
问题是代码的行为及其类型注释彼此处于交叉目的.
实际上,我会说代码被过度注释. 通过基于类型推断和基于控制流的类型分析,联合类型和案例分析可以实现,这是TypeScript最强大的两个特性.类型检查器消除联合可能性的过程称为缩小. 如代码所示,通过对称为判别式的属性执行值测试,可以将联合类型分解为其组成部分. 判别式是一种属性,其类型具有有限的可能值集,每个值通常对应于并集的情况. string不是有效的判别式,但“hello world”是. (作为所有可能字符串的超类型,字符串类型的联合,包括字符串折叠到只是字符串) 当我们在TypeScript中定义const或readonly属性时,编译器会将其类型推断为初始化文本的类型. 考虑: const kind = "first"; 这种类型不是字符串而是“第一”. 同样,给定 class Kindred { readonly kind = "first"; } 属性类型不是字符串而是“第一”. 在我们的代码中,判别式是一个名为type的属性,由union的每个成员定义. 但是,虽然您已为每个成员正确提供了唯一值,但您已使用类型注释过度指定它们以防止缩小. 你有什么: export class AddSuccessAction { public readonly type: string = ADD_SUCCESS; constructor(public payload: Mission) {} } export class AddFailedAction { public readonly type: string = ADD_FAILED; constructor(public payload: string) {} } 你想要什么: export class AddSuccessAction { readonly type = ADD_SUCCESS; constructor(public payload: Mission) {} } export class AddFailedAction { readonly type = ADD_FAILED; constructor(public payload: string) {} } 一个工作开关 switch (action.type) { // action.type is `"[Mission] AddSuccess" | "[Mission] AddFailed"` // action.payload is `string | Mission` case missionActions.ADD_SUCCESS: // action.type is `"[Mission] AddSuccess"` // action.payload is `Mission` const mission = action.payload; } 为什么这很重要: 字符串文字类型是区分联合可能性的常用和惯用方式,但是,通过将实现属性声明为字符串类型,类型是所有字符串文字类型的超类型,我们禁止类型推断,从而防止缩小.请注意,字符串不是可以缩小的类型. 通常,当值具有初始值设定项时,最好利用TypeScript的类型推断.除了启用预期方案之外,类型推理器将捕获的错误数量将给您留下深刻印象.我们不应该告诉编译器超出它需要知道的内容,除非我们故意想要一种比它推断的更通用的类型.使用–noImplicitAny,当我们需要以类型注释的形式指定额外信息时,它总是会告诉我们. 备注: 您可以在技术上指定类型,并通过将文字值指定为const或readonly属性的类型来保留缩小行为.然而,这增加了维护成本并且相当多余. 例如,以下内容有效: export const ADD_FAILED: "[Mission] AddFailed" = "[Mission] AddFailed"; 但你只是在不必要地重复自己. 在他们的回答中,ilyabasiuk提供了一些很好的参考链接,特别是与ngrx一起使用文字类型,以及它是如何在最近的TypeScript语言迭代中进化的. 要理解为什么在不可变位置推断文字类型,请考虑它可以实现强大的静态分析,从而更好地检测错误. 考虑: type Direction = "N" | "E" | "S" | "W"; declare function getDirection(): Direction; const currentDirection = getDirection(); if (currentDirection === "N") { // currentDirection is "N" | "E" | "S" | "W" } // Error: this is impossible,unreachable code as currentDirection is "E" | "S" | "W" // the compiler knows and will give us an error here. else if (currentDirection === "N") { } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |