[英]Generic typing a store of a given type
我正在創建一個商店應該能夠擴展的自定義 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))
}
}
有任何想法嗎? 不能說我已經使用過 generics,所以這將是一次很棒的學習體驗。
編輯:映射類型似乎有一個缺點。 商店的update()
function 不起作用:
// 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>'
}
我不確定“整個事情都崩潰了”到底是什么意思(通常是一個最小可重復的例子,它表明你的意思比文字更有幫助),但假設你想跟蹤state
的每個鍵及其相應屬性的data
類型,我建議使用映射類型來表示StoreState<T>
以表示這些鍵/數據關系的 object 類型T
。
type StoreState<T> = { [K in keyof T]: Partial<LoadableState<T[K]>> };
然后,假設BaseStore<T>
有一個構造函數來設置其state
屬性:
class BaseStore<T> {
constructor(public state: StoreState<T>) { }
}
您應該能夠使用 object 構建一個:
const bs = new BaseStore({
something: {
data: {
todos: [1, 2, 3] // 🤷♂️
},
loading: false,
error: {}
},
somethingElse: {
data: {
items: ["a", "b", "c"] // 🤷♀️
},
loading: false,
error: {}
}
});
您會看到構造的 object 的類型已被推斷(通過映射類型的推斷),如下所示:
/*
const bs: BaseStore<{
something: {
todos: number[];
};
somethingElse: {
items: string[];
};
}>*/
所以這里推斷的T
是{something: {todos: number[]}; somethingElse: {items: string[]};}
{something: {todos: number[]}; somethingElse: {items: string[]};}
我想,你想要的。
希望有幫助; 祝你好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.