我理解以下打字稿错误的内容虽然我不明白为什么,因为A
类型正在扩展IReduxAction
并且在其他地方指定extends IReduxAction
。
这里的任何帮助都会很棒。
这是错误
Type '{ ACTION_NAME: IReducer<ISt, IAction<"hello", string>>; }' is not assignable to type 'TCaseFunctions<ISt>'.
Property 'ACTION_NAME' is incompatible with index signature.
Type 'IReducer<ISt, IAction<"hello", string>>' is not assignable to type '<A extends IReduxAction>(state: Readonly<ISt>, action: A) => ISt'.
Types of parameters 'action' and 'action' are incompatible.
Type 'A' is not assignable to type 'IAction<"hello", string>'.
Type 'IReduxAction' is not assignable to type 'IAction<"hello", string>'.
Property 'payload' is missing in type 'IReduxAction'.
这是代码。您可以将其直接粘贴到https://www.typescriptlang.org/play/index.html
的游乐场export interface IReduxAction {
type: any
}
export interface IGenericAction<T, P, M> extends IReduxAction {
type: T
payload: P
meta?: M
}
export interface IAction<T, P> extends IGenericAction<T, P, any> {}
export type IReducer<S, A extends IReduxAction> =
(state: Readonly<S>, action: A) => S
export type TCaseFunctions<S> = {
[action: string]: <A extends IReduxAction>(state: Readonly<S>, action: A) => S
}
interface ISt { a: string }
type MyAction = IAction<'hello', string>
const basicAction: IReduxAction = {
type: 'foo'
}
const reducer: IReducer<ISt, MyAction> = (state, action) => state
const caseFunctions: TCaseFunctions<ISt> = {
ACTION_NAME: reducer
}
const rootReducer = createReducer<ISt>(caseFunctions)
// rootReducer(state, { type: 'hello', payload: 'foobar' })
答案 0 :(得分:0)
TCaseFunction
被定义为具有通用函数签名,因此在调用时,可以传入任何操作:
caseFunction({} as ISt, {} as MyAction)
caseFunction({} as ISt, {} as MyOtherAction)
您尝试分配给caseFunction
的功能不是通用的,它需要采取特定操作(MyAction
),因此它不尊重TCaseFunction
定义的合同。
您可以将签名的通用参数添加到TCaseFunction
,然后事情会按预期工作:
export type TCaseFunction<S, A> = (state: Readonly<S>, action: A) => S
const caseFunction: TCaseFunction<ISt, MyAction> = reducer
修改强>
关于泛型函数与非泛型函数不兼容的更多细节。请考虑以下示例:
type genericFunction = <A>(param: A) => A;
let ok:genericFunction = function <A>( param: A) { return param};
// We can pass to the function any type A
ok(1); // be it int
ok(""); // or string
let notOk:genericFunction = function (param: string ){ return param.substr(1);}
// The above assignment is not allowed because the signature for genericFunction mandates that it be able to handle any A not just a specific A
// genericFunction allows either of these:
notOk(""); // We can pass a string, as the implementation expects
notOk(1); // but we can pass an int, which the implementation would not know how to process
<强> EDIT2 强>
在你的情况下,你似乎并不真正关心A
是什么,只是它是一个动作,你可以使用以下定义taht将强制所有成员成为第二个参数为任何IReduxAction的函数:
export type TCaseFunctions<S> = {
[action: string]: (state: Readonly<S>, action: IReduxAction) => S;
}