使用NgRx createSelector获取Observable遇TS2740错误的解决方法
NgRx 15 createSelector 使用错误导致TS2740问题
问题背景
原本从NgRx Store获取数据的传统写法:
public getUser(): Observable<IUser> { return this.store.select(store => store.users.selectedUser); }
尝试改用NgRx 15的createSelector方法后,代码写成这样:
public getUser(): Observable<IUser> { const user = createSelector((state: IAppState) => state.users, (userState) => { return userState; } ); return user; }
出现TS2740错误:
TS2740: Type 'MemoizedSelector<IAppState, IUserState, (s1: IUserState) => IUserState>' is missing the following properties from type 'Observable
': source, operator, lift, subscribe, and 3 more.
需求是让getUser()返回Observable<IUser>,以支持如下订阅操作:
this.storeSelector.getUser().subscribe((a) => { console.log(a); });
问题原因
createSelector的作用是创建一个记忆化的选择器函数,它本身返回的是MemoizedSelector类型,并不是Observable。直接返回这个选择器,不符合方法声明的Observable<IUser>返回类型,因此触发TypeScript类型错误。另外当前选择器返回的是整个userState,和原代码要获取的selectedUser类型不匹配,也会导致后续类型问题。
解决方法
需要将创建好的选择器传入store.select()方法,才能得到对应数据的Observable,同时修正选择器逻辑,确保返回正确的IUser类型数据。
推荐写法(复用选择器,保留记忆化优势)
// 在类外部或共享模块中定义可复用的选择器 const selectUserState = (state: IAppState) => state.users; const selectSelectedUser = createSelector( selectUserState, (userState) => userState.selectedUser ); // 类方法中调用选择器并转换为Observable public getUser(): Observable<IUser> { return this.store.select(selectSelectedUser); }
方法内部创建选择器(不推荐,每次调用都会生成新选择器,丢失记忆化效果)
public getUser(): Observable<IUser> { const selectSelectedUser = createSelector( (state: IAppState) => state.users, (userState) => userState.selectedUser ); return this.store.select(selectSelectedUser); }
修改后,store.select()会将选择器转换为对应数据的Observable,既能正常执行订阅操作,也能通过TypeScript的类型检查。
内容的提问来源于stack exchange,提问作者born2net
相关产品推荐
相关产品推荐

