typescript NgRX在createAction属性中使用泛型类型

aydmsdu9  于 2022-11-26  发布在  TypeScript
关注(0)|答案(1)|浏览(115)

在我开始之前,另一个人问了an already same question,但那似乎已经过时了,答案不再解决问题。
我的问题和那个问题中描述的一样。我使用@ngrx/store版本14.3.0。我想创建一个函数,根据传递的参数创建操作。例如:

import { createAction, props } from '@ngrx/store';

export function loadContent<TParams extends object>(key: string) {
    return createAction(
        `[${key}] Load ${key}`,
        props<TParams>()
        // ^^^^^^^^^^^^^
    );
}

这个被截取的代码会导致编译器错误,因为TParams不符合props函数的类型要求。以下是完整的错误代码:

Error: libs/state/content-primitives/src/lib/content-actions.ts:7:9 - error TS2769: No overload matches this call.
  Overload 1 of 3, '(type: `[${string}] Load ${string}`, config: ActionCreatorProps<TParams> & NotAllowedCheck<TParams>): ActionCreator<`[${string}] Load ${string}`, (props: TParams & NotAllowedCheck<...>) => TParams & TypedAction<...>>', gave the following error.
    Argument of type 'ActionCreatorProps<TParams>' is not assignable to parameter of type 'ActionCreatorProps<TParams> & NotAllowedCheck<TParams>'.
      Type 'ActionCreatorProps<TParams>' is not assignable to type 'NotAllowedCheck<TParams>'.
  Overload 2 of 3, '(type: `[${string}] Load ${string}`, creator: Creator<any[], never>): FunctionWithParametersType<any[], object & TypedAction<`[${string}] Load ${string}`>> & TypedAction<...>', gave the following error.
    Argument of type 'ActionCreatorProps<TParams>' is not assignable to parameter of type 'Creator<any[], never>'.
      Type 'ActionCreatorProps<TParams>' provides no match for the signature '(...args: any[]): never'.

7         props<TParams>()
          ~~~~~~~~~~~~~~~~


Error: libs/state/content-primitives/src/lib/content-actions.ts:7:15 - error TS2344: Type 'TParams' does not satisfy the constraint 'NotAllowedInPropsCheck<TParams>'.
  Type 'object' is not assignable to type 'NotAllowedInPropsCheck<TParams>'.

7         props<TParams>()
                ~~~~~~~

在此之后,我尝试将此类型参数与props的NgRX源代码中定义的类型参数完全匹配。我基本上将泛型类型定义粘贴到我的代码中:

import { createAction, props } from '@ngrx/store';
import { NotAllowedInPropsCheck } from '@ngrx/store/src/models';

export function loadContent<TParams extends SafeProps, SafeProps = NotAllowedInPropsCheck<TParams>>(key: string) {
    return createAction(
        `[${key}] Load ${key}`,
        props<TParams>()
        // ^^^^^^^^^^^^^
    );
}

这一个也没有做到这一点,并失败了以下编译错误:

Error: libs/state/content-primitives/src/lib/content-actions.ts:7:9 - error TS2769: No overload matches this call.
  Overload 1 of 3, '(type: `[${string}] Load ${string}`, config: ActionCreatorProps<object> & "action creator cannot return an empty object"): ActionCreator<`[${string}] Load ${string}`, (props: never) => object & TypedAction<...>>', gave the following error.
    Argument of type 'ActionCreatorProps<TParams>' is not assignable to parameter of type 'ActionCreatorProps<object> & "action creator cannot return an empty object"'.
      Type 'ActionCreatorProps<TParams>' is not assignable to type 'ActionCreatorProps<object>'.
        Type 'TParams' is not assignable to type 'object'.
          Type 'SafeProps' is not assignable to type 'object'.
  Overload 2 of 3, '(type: `[${string}] Load ${string}`, creator: Creator<any[], never>): FunctionWithParametersType<any[], object & TypedAction<`[${string}] Load ${string}`>> & TypedAction<...>', gave the following error.
    Argument of type 'ActionCreatorProps<TParams>' is not assignable to parameter of type 'Creator<any[], never>'.
      Type 'ActionCreatorProps<TParams>' provides no match for the signature '(...args: any[]): never'.

7         props<TParams>()
          ~~~~~~~~~~~~~~~~

  libs/state/content-primitives/src/lib/content-actions.ts:4:56
    4 export function loadContent<TParams extends SafeProps, SafeProps = NotAllowedInPropsCheck<TParams>>(key: string) {
                                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    This type parameter might need an `extends object` constraint.

Error: libs/state/content-primitives/src/lib/content-actions.ts:7:15 - error TS2344: Type 'TParams' does not satisfy the constraint 'NotAllowedInPropsCheck<TParams>'.
  Type 'SafeProps' is not assignable to type 'NotAllowedInPropsCheck<TParams>'.

7         props<TParams>()
                ~~~~~~~

  libs/state/content-primitives/src/lib/content-actions.ts:4:56
    4 export function loadContent<TParams extends SafeProps, SafeProps = NotAllowedInPropsCheck<TParams>>(key: string) {
                                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    This type parameter might need an `extends NotAllowedInPropsCheck<TParams>` constraint.

错误声明SafeProps不能赋值给object类型,但我不明白它怎么会是NotAllowedInPropsCheck<TParams>泛型类型,因为NotAllowedInPropsCheck<TParams>会检查提供的类型是否是object
还有,完全相同的泛型类型公式怎么可能不适用于这里。我正在寻找一个解决方案,我可以使这个编译不使用any类型。

hgncfbus

hgncfbus1#

NgRx基本上强制一个带有键的对象作为action的有效载荷。这意味着,在该对象内,你可以有任何东西,但在根级别上,你需要有一个至少带有一个键的对象(不允许空对象)。下面是一个相对简单的修复方法:

export function loadContent<TParams>(key: string) {
  return createAction(
      `[${key}] Load ${key}`,
      (payload: TParams) => ({payload}),
  );
}

const action = loadContent<number>('Content');

action({payload: 6});

如果您不喜欢在每次调度操作时都添加payload键,可以放弃props函数,并以简单的方式提供手动实现:

export function loadContent<TParams>(key: string) {
  return createAction(
      `[${key}] Load ${key}`,
      (payload: TParams) => ({payload}),
  );
}

const load = loadContent<number>('Content');

load(6);

相关问题