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

如何让NgRx selectSignal返回的Signal变量触发TypeScript编译错误?

NgRx selectSignal() 返回对象可直接赋值但TypeScript无编译错误的问题及解决办法

问题说明

用NgRx的selectSignal()从Store里选状态切片时,它返回的是对象类型的Signal而非Observable,这部分运行没问题。但要是直接修改Signal返回对象的属性,TypeScript编译阶段不会报错,只有运行时才会崩溃,没法提前发现问题。

错误代码示例

// 定义并初始化signal变量
public voucherFilterSignal: Signal<VoucherFilter> =
    this._store.selectSignal(selectVoucherFilter);

// 直接修改signal返回对象的属性(编译无提示,运行时崩溃)
this.voucherFilterSignal().search = 'someNewValue';

可行解决方案

声明Signal变量时,给泛型参数加上Readonly类型,这样TypeScript编译器就能在编辑阶段直接捕获错误:

public voucherFilterSignal: Signal<Readonly<VoucherFilter>> =
    this._store.selectSignal(selectVoucherFilter);

// 此时编译阶段会触发错误:"Cannot assign to 'search' because it is a read-only property.ts(2540)"
this.voucherFilterSignal().search = 'someNewValue';

为什么默认不设置只读

NgRx没把selectSignal()返回的Signal泛型默认设为Readonly,主要是这几个原因:

  • 兼容灵活场景:有些开发者可能会先修改状态对象的局部属性,再通过action提交到Store(这不是推荐做法,但框架需要兼容这类场景)。
  • 类型推断低侵入:默认不添加只读约束,能让类型更贴近原始状态的定义,不会强制给所有状态类型加只读限制,给开发者自主选择的空间。
  • 运行时保护作为补充:NgRx在运行时会拦截对Store状态的直接修改,这是最后一道防线,但编译阶段的类型约束需要开发者主动开启,以此提前规避问题。

内容的提问来源于stack exchange,提问作者Bjarne Gerhardt-Pedersen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 00:04:58