如何让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
相关产品推荐
相关产品推荐

