我正在创建一个自定义的Redux存储,该存储应该可以扩展。我的目标是这样的:
class BaseStore<T> {
public state$: Observable<StoreState<T>>;
...
// other helpers and the like
}
StoreState
如下:
export type ErrorState = Record<string, any>;
export type LoadableState<T> = {
data: T;
loading: boolean;
error: ErrorState;
};
export type StoreState<T> = Record<string, Partial<LoadableState<T>>>;
但是我不能正确输入。可以,但是如果您想在商店中有两个这样的商品:
{ // this object represents the store which consists of LoadableStates
something: { // I want to type the "slices" in the store
data: { // and also to be able to type what is in data
todos: []
},
loading: false,
error: {}
},
somethingElse: {
data: {
items: []
},
loading: false,
error: {}
}
}
整个事情都崩溃了;意思是,我不能继续输入类似的内容:
interface SomethingState {
email?: string;
username?: string;
}
interface SomethingElseState {
todos?: Array<Record<string,string>>;
saveSuccess?: Record<string, string | boolean>;
}
interface MyStoreState {
something?: SomethingState;
somethingElse?: SomethingElseState;
}
class MyStore extends BaseStore<MyStoreState> {
...
public getEmail(): Observable<string> {
return this.state$.pipe(map(state => state.something.data.email))
}
}
有什么想法吗?不能说我已经使用了泛型,所以这将是一次很棒的学习经历。
编辑:映射的类型似乎有缺点。该商店的update()
函数无法正常工作:
// my implementation for updating the store
public set(nextState: StoreState<T>): void {
this.state$.next(nextState);
}
public update(storeSlice: string, partialState: Partial<LoadableState<T>>): void {
if (!this.stateValue[storeSlice]) {
throw Error('Path does not exist in the store');
}
const currentState = this.stateValue[storeSlice];
const nextState = merge(currentState, partialState); // lodash's merge
this.set({ [storeSlice]: { ...nextState } }); // ERROR: Argument of type '{ [x: string]: any; }' is not assignable to parameter of type 'StoreState<T>'
}
答案 0 :(得分:2)
我不确定“整个事情都崩溃了”的含义是什么(通常是minimum reproducible example,它表明您的意思总比说单词更有用),但假设您想跟踪state
的每个键及其相应属性的data
类型,我建议使用mapped type来表示StoreState<T>
,以对象类型{{1} },代表这些键/数据关系。
T
然后,假设type StoreState<T> = { [K in keyof T]: Partial<LoadableState<T[K]>> };
具有用于设置其BaseStore<T>
属性的构造函数:
state
您应该能够使用您的对象构造一个对象
class BaseStore<T> {
constructor(public state: StoreState<T>) { }
}
,您将看到已构造对象的类型(通过inference from mapped types推断)是这样的:
const bs = new BaseStore({
something: {
data: {
todos: [1, 2, 3] // ?♂️
},
loading: false,
error: {}
},
somethingElse: {
data: {
items: ["a", "b", "c"] // ?♀️
},
loading: false,
error: {}
}
});
因此,我认为您想要的是/*
const bs: BaseStore<{
something: {
todos: number[];
};
somethingElse: {
items: string[];
};
}>*/
。{p>
希望有所帮助;祝好运!