好吧,我想我找到了办法。如果我为我让 RootState 实现的每个状态片创建一个接口,并在我的选择器中引用它,那么它似乎可以工作。以下是基本方法:
interface User {
id: number;
name: string
}
interface UsersSlice {
users: User[];
}
const selectUsers = (state: UsersSlice) => state.users;
interface RootState extends UsersSlice {
}
class MyComponent {
private data: Observable<User[]>;
constructor(private store: Store<RootState>) {
this.data = store.select(selectUsers);
}
}
总体而言,该方法不会添加太多样板,因为无论如何您都必须定义 RootState。在这种方法中,您只需将其从“切片状态”中组合出来。然后你可以只引用你关心的粒度切片而不是世界。
如果你有很多选择器跨越不同的状态片,它可能会爆炸一点。如果您引用 RootState 那么它是不可移植的。您可以创建一个接口来扩展您想要的状态片段,如下所示:
interface Foo {
id: number;
}
interface Bar {
id: string;
}
interface FooBar {
foo: Foo;
bar: Bar;
}
interface FooSlice {
foo: Foo;
}
interface BarSlice {
bar: Bar;
}
const selectFoo = (state: FooSlice) => state.foo;
const selectBar = (state: BarSlice) => state.bar;
const selectFooBar = createSelector<FooBarSlice, Foo, Bar, FooBar>(
selectFoo,
selectBar,
(foo: Foo, bar: Bar) => (<FooBar>{ foo, bar })
)
interface FooBarSlice extends FooSlice, BarSlice {}
interface RootSlice extends FooSlice, BarSlice, FooBarSlice {
...
}
因此,在最坏的情况下,您最终可能得到的接口数量等于所有可能的切片组合的数量。
更合理的选择是创建这样的临时交叉点 (FooSlice & BarSlice):
const selectFooBar = createSelector<FooSlice & BarSlice, Foo, Bar, FooBar>(
selectFoo,
selectBar,
(foo: Foo, bar: Bar) => (<FooBar>{ foo, bar })
)
对于特征切片中的状态,您必须按如下方式对其进行修改:
interface FeatureRoot extends FooSlice, BarSlice {}
const featureKey = 'feature';
interface FooState { 'feature': FooSlice; }
interface BarState { 'feature': BarSlice; }
type FeatureState = RootState & FooState & BarState;
const selectFeatureState = createFeatureSelector<FeatureRoot>(featureKey);
const selectFooState = createFeatureSelector<FooSlice>(featureKey);
const selectBarState = createFeatureSelector<BarSlice>(featureKey);
const selectFoo = createSelector(selectFooState, x => x.foo);
const selectBar = createSelector(selectBarState, x => x.bar);
class MyComponent {
private foo: Observable<Foo>;
private bar: Observable<Bar>;
constructor(private store: Store<FeatureState>) {
this.foo = store.select(selectFoo);
this.bar = store.select(selectBar);
}
}