【发布时间】:2021-09-02 17:34:29
【问题描述】:
我有一个非常棘手的关于泛型和部分的 TypeScript 问题。
这个问题的游乐场是here
我将使用 React 术语解释这个问题,尽管它与 React 没有直接关系。
有一个自定义的 React 钩子,它基本上使用 useReducer 创建了一个 reducer,它包含一些通用属性,以及一个通用的 data 属性。
让我们假设这是钩子:
interface IState<T> {
some: string;
data: T;
}
type Action<T> = { type: 'UPDATE_STATE'; payload: Partial<T> };
const foo = <T>(initalState: T) => {
const state: IState<T> = { some: 'foo', data: initalState };
const dispatch = (action: Action<T>) => {
// do something
}
return {state, dispatch};
};
此外,还有另一个自定义钩子,它实际上通过向 state reducer 添加额外的公共属性来扩展第一个:
interface MyBar {
extraData: string;
}
const bar = <T>(initialState: T) => {
const {state, dispatch} = foo<T & MyBar>({ ...initialState, extraData: 'some data' });
return { state, dispatch };
}
现在,一个典型的用法是:
const baz = () => {
const { state, dispatch } = bar<IMyState>({ name: 'mor' });
console.log(state, dispatch)
}
所以在baz,我的状态对象将是:
{
"extraData": "some data",
"some": "foo",
"data": {
"name": "mor"
}
}
到目前为止一切顺利。现在我想做以下更改:
const bar = <T>(initialState: T) => {
const {state, dispatch} = foo<T & MyBar>({ ...initialState, extraData: 'some data' });
**dispatch({ type: 'UPDATE_STATE', payload: { extraData: 'changed' } });**
return { state, dispatch };
}
我得到:
Type '{ extraData: "changed"; }' is not assignable to type 'Partial<T & MyBar>'.(2322)
input.ts(7, 42): The expected type comes from property 'payload' which is declared here on type 'Action<T & MyBar>'
我不确定为什么会发生这种情况,因为bar 将泛型类型与额外数据一起传递,我希望foo 能够允许它。
如果有任何建议,我将不胜感激!
【问题讨论】:
-
在这种情况下您不应该使用
|而不是&吗? -
foo<T | MyBar>({ ...initialState, extraData: 'some data' })为我解决了这个问题,但需要更深入地了解上下文,如果它有任何业务影响 -
@SamridhTuladhar 不幸的是,情况并非如此,
|不能保证我有来自扩展和通用有效负载的密钥,它可以是任何一个,但不能两者兼有。 -
在
baz状态对象应该是{ data: { extraData: string, name: string }, …}。注意extraData嵌套在data中。
标签: typescript