Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Handle breaking changes in NgRx actions #19013

Closed
wants to merge 23 commits into from

Conversation

Platonn
Copy link
Contributor

@Platonn Platonn commented Jun 27, 2024

In previous past PR within this Epic branch, we've made breaking changes - changing constructor signatures of ngrx actions from having error: any to error: <something more specific> (i.e. error: ErrorActionType). In this PR, we revert this change - allowing for error: any but at the same time deprecating it. Moreover, the non-deprecated constructor requires the value to be non-null, non-undefined.

fixes https://jira.tools.sap/browse/CXSPA-7198 (it's part 1/2; the part 2/2 - adding implements ErrorAction - will arrive in a separate PR for the breviety of this PR)

QA steps
To conduct the QA steps, please add the code snippets given below to your app.module.ts (please make sure to import the pasted items; note: for auto-adding missing imports in VSCode you might find this trick helpful).

Table of contents:

  1. ⚠️ deprecated optional error (just in EntityFailAction)
  2. ⚠️ deprecated undefined error
  3. ⚠️ deprecated null error
  4. ⚠️ deprecated any error
  5. ⚠️ deprecated unknown error
  6. ✅ valid plain object error
  7. ✅ valid empty object error
  8. ✅ valid empty string error

  1. ⚠️ DEPRECATED OPTIONAL verify it's deprecated to omit the optional error? 3rd argument in the action EntityFailAction (it's the only one example with optional error? argument. the rest of actions in examples below have a required error param).
export const entityLoaderAction_optionalLastArgError = new EntityFailAction(
  'entityType',
  'entityId'
);

(screenshot: )
image

  1. ⚠️ DEPRECATED UNDEFINED - Verify it's deprecated to pass undefined error object to various actions, e.g. that in your VSCode the names of the constructed classes are crossed out:
const errorUndefined = undefined;
export const actionsUsing_errorUndefined = [
  new LoadCdcUserTokenFail({
    initialActionPayload: {
      baseSite: 'testBaseSite',
      idToken: 'testIdToken',
      signatureTimestamp: 'testSignatureTimestamp',
      UID: 'testUID',
      UIDSignature: 'testUIDSignature',
    },
    error: errorUndefined,
  }),
  new CustomerSearchFail(errorUndefined),
  new CartAddEntryFail({
    cartId: 'testCartId',
    error: errorUndefined,
    productCode: 'testProductCode',
    quantity: 1,
    userId: 'testUserId',
    pickupStore: 'testPickupStore',
  }),
  new EditSavedCartFail({
    cartId: 'testCartId',
    error: errorUndefined,
    userId: 'testUserId',
    saveCartName: 'testSaveCartName',
  }),
  new LoadWishListFail({
    cartId: 'testCartId',
    error: errorUndefined,
  }),
  new CancelReplenishmentOrderFail({
    message: 'error',
  }),
  new UnassignB2BUserUserGroupFail({
    error: errorUndefined,
    orgCustomerId: 'testOrgCustomerId',
    userGroupId: 'testUserGroupId',
  }),
  new AssignBudgetFail({
    budgetCode: 'testBudgetCode',
    error: errorUndefined,
  }),
  new LoadApprovalProcessesFail({
    error: errorUndefined,
  }),
  new LoadPermissionTypesFail({
    error: errorUndefined,
  }),
  new LoadUnitOrdersFail(errorUndefined),
  new LoadCmsComponentFail({
    error: errorUndefined,
    pageContext: { id: 'testPageId', type: PageType.CONTENT_PAGE },
    uid: 'testUid',
  }),
  new LoadCmsNavigationItemsFail('nodeId', errorUndefined),
  new LoadProductFail('productCode123', errorUndefined, 'scope'),
  new LoadUserConsentsFail(errorUndefined),
  new EntityFailAction('entityType', 'entityId', errorUndefined),
];

(screenshot: )
image

  1. ⚠️ DEPREACTED NULL
const errorNull = null;
export const actionsUsing_errorNull = [
  new LoadCdcUserTokenFail({
    initialActionPayload: {
      baseSite: 'testBaseSite',
      idToken: 'testIdToken',
      signatureTimestamp: 'testSignatureTimestamp',
      UID: 'testUID',
      UIDSignature: 'testUIDSignature',
    },
    error: errorNull,
  }),
  new CustomerSearchFail(errorNull),
  new CartAddEntryFail({
    cartId: 'testCartId',
    error: errorNull,
    productCode: 'testProductCode',
    quantity: 1,
    userId: 'testUserId',
    pickupStore: 'testPickupStore',
  }),
  new EditSavedCartFail({
    cartId: 'testCartId',
    error: errorNull,
    userId: 'testUserId',
    saveCartName: 'testSaveCartName',
  }),
  new LoadWishListFail({
    cartId: 'testCartId',
    error: errorNull,
  }),
  new CancelReplenishmentOrderFail({
    message: 'error',
  }),
  new UnassignB2BUserUserGroupFail({
    error: errorNull,
    orgCustomerId: 'testOrgCustomerId',
    userGroupId: 'testUserGroupId',
  }),
  new AssignBudgetFail({
    budgetCode: 'testBudgetCode',
    error: errorNull,
  }),
  new LoadApprovalProcessesFail({
    error: errorNull,
  }),
  new LoadPermissionTypesFail({
    error: errorNull,
  }),
  new LoadUnitOrdersFail(errorNull),
  new LoadCmsComponentFail({
    error: errorNull,
    pageContext: { id: 'testPageId', type: PageType.CONTENT_PAGE },
    uid: 'testUid',
  }),
  new LoadCmsNavigationItemsFail('nodeId', errorNull),
  new LoadProductFail('productCode123', errorNull, 'scope'),
  new LoadUserConsentsFail(errorNull),
  new EntityFailAction('entityType', 'entityId', errorNull),
];

(screenshot: )
image

  1. ⚠️ DEPRECATED ANY
const errorAny: any = <any>{ something: 'but casted to any' };
export const actionsUsing_errorAny = [
  new LoadCdcUserTokenFail({
    initialActionPayload: {
      baseSite: 'testBaseSite',
      idToken: 'testIdToken',
      signatureTimestamp: 'testSignatureTimestamp',
      UID: 'testUID',
      UIDSignature: 'testUIDSignature',
    },
    error: errorAny,
  }),
  new CustomerSearchFail(errorAny),
  new CartAddEntryFail({
    cartId: 'testCartId',
    error: errorAny,
    productCode: 'testProductCode',
    quantity: 1,
    userId: 'testUserId',
    pickupStore: 'testPickupStore',
  }),
  new EditSavedCartFail({
    cartId: 'testCartId',
    error: errorAny,
    userId: 'testUserId',
    saveCartName: 'testSaveCartName',
  }),
  new LoadWishListFail({
    cartId: 'testCartId',
    error: errorAny,
  }),
  new CancelReplenishmentOrderFail({
    message: 'error',
  }),
  new UnassignB2BUserUserGroupFail({
    error: errorAny,
    orgCustomerId: 'testOrgCustomerId',
    userGroupId: 'testUserGroupId',
  }),
  new AssignBudgetFail({
    budgetCode: 'testBudgetCode',
    error: errorAny,
  }),
  new LoadApprovalProcessesFail({
    error: errorAny,
  }),
  new LoadPermissionTypesFail({
    error: errorAny,
  }),
  new LoadUnitOrdersFail(errorAny),
  new LoadCmsComponentFail({
    error: errorAny,
    pageContext: { id: 'testPageId', type: PageType.CONTENT_PAGE },
    uid: 'testUid',
  }),
  new LoadCmsNavigationItemsFail('nodeId', errorAny),
  new LoadProductFail('productCode123', errorAny, 'scope'),
  new LoadUserConsentsFail(errorAny),
  new EntityFailAction('entityType', 'entityId', errorAny),
];

(screenshot: )
image

  1. ⚠️ DEPRECATED UNKNOWN
const errorUnknown: unknown = <unknown>{ something: 'but casted to unknown' };
export const actionsUsing_errorUnknown = [
  new LoadCdcUserTokenFail({
    initialActionPayload: {
      baseSite: 'testBaseSite',
      idToken: 'testIdToken',
      signatureTimestamp: 'testSignatureTimestamp',
      UID: 'testUID',
      UIDSignature: 'testUIDSignature',
    },
    error: errorUnknown,
  }),
  new CustomerSearchFail(errorUnknown),
  new CartAddEntryFail({
    cartId: 'testCartId',
    error: errorUnknown,
    productCode: 'testProductCode',
    quantity: 1,
    userId: 'testUserId',
    pickupStore: 'testPickupStore',
  }),
  new EditSavedCartFail({
    cartId: 'testCartId',
    error: errorUnknown,
    userId: 'testUserId',
    saveCartName: 'testSaveCartName',
  }),
  new LoadWishListFail({
    cartId: 'testCartId',
    error: errorUnknown,
  }),
  new CancelReplenishmentOrderFail({
    message: 'error',
  }),
  new UnassignB2BUserUserGroupFail({
    error: errorUnknown,
    orgCustomerId: 'testOrgCustomerId',
    userGroupId: 'testUserGroupId',
  }),
  new AssignBudgetFail({
    budgetCode: 'testBudgetCode',
    error: errorUnknown,
  }),
  new LoadApprovalProcessesFail({
    error: errorUnknown,
  }),
  new LoadPermissionTypesFail({
    error: errorUnknown,
  }),
  new LoadUnitOrdersFail(errorUnknown),
  new LoadCmsComponentFail({
    error: errorUnknown,
    pageContext: { id: 'testPageId', type: PageType.CONTENT_PAGE },
    uid: 'testUid',
  }),
  new LoadCmsNavigationItemsFail('nodeId', errorUnknown),
  new LoadProductFail('productCode123', errorUnknown, 'scope'),
  new LoadUserConsentsFail(errorUnknown),
  new EntityFailAction('entityType', 'entityId', errorUnknown),
];

(screenshot: )
image

  1. VALID PLAIN OBJECT
const errorPlainObject = { message: 'error message 1' };
export const actionsUsing_errorPlainObject = [
  new LoadCdcUserTokenFail({
    initialActionPayload: {
      baseSite: 'testBaseSite',
      idToken: 'testIdToken',
      signatureTimestamp: 'testSignatureTimestamp',
      UID: 'testUID',
      UIDSignature: 'testUIDSignature',
    },
    error: errorPlainObject,
  }),
  new CustomerSearchFail(errorPlainObject),
  new CartAddEntryFail({
    cartId: 'testCartId',
    error: errorPlainObject,
    productCode: 'testProductCode',
    quantity: 1,
    userId: 'testUserId',
    pickupStore: 'testPickupStore',
  }),
  new EditSavedCartFail({
    cartId: 'testCartId',
    error: errorPlainObject,
    userId: 'testUserId',
    saveCartName: 'testSaveCartName',
  }),
  new LoadWishListFail({
    cartId: 'testCartId',
    error: errorPlainObject,
  }),
  new CancelReplenishmentOrderFail({
    message: 'error',
  }),
  new UnassignB2BUserUserGroupFail({
    error: errorPlainObject,
    orgCustomerId: 'testOrgCustomerId',
    userGroupId: 'testUserGroupId',
  }),
  new AssignBudgetFail({
    budgetCode: 'testBudgetCode',
    error: errorPlainObject,
  }),
  new LoadApprovalProcessesFail({
    error: errorPlainObject,
  }),
  new LoadPermissionTypesFail({
    error: errorPlainObject,
  }),
  new LoadUnitOrdersFail(errorPlainObject),
  new LoadCmsComponentFail({
    error: errorPlainObject,
    pageContext: { id: 'testPageId', type: PageType.CONTENT_PAGE },
    uid: 'testUid',
  }),
  new LoadCmsNavigationItemsFail('nodeId', errorPlainObject),
  new LoadProductFail('productCode123', errorPlainObject, 'scope'),
  new LoadUserConsentsFail(errorPlainObject),
  new EntityFailAction('entityType', 'entityId', errorPlainObject),
];

(screenshot: )
image

  1. VALID EMPTY OBJECT
const errorEmptyObject = {};
export const actionsUsing_errorEmptyObject = [
  new LoadCdcUserTokenFail({
    initialActionPayload: {
      baseSite: 'testBaseSite',
      idToken: 'testIdToken',
      signatureTimestamp: 'testSignatureTimestamp',
      UID: 'testUID',
      UIDSignature: 'testUIDSignature',
    },
    error: errorEmptyObject,
  }),
  new CustomerSearchFail(errorEmptyObject),
  new CartAddEntryFail({
    cartId: 'testCartId',
    error: errorEmptyObject,
    productCode: 'testProductCode',
    quantity: 1,
    userId: 'testUserId',
    pickupStore: 'testPickupStore',
  }),
  new EditSavedCartFail({
    cartId: 'testCartId',
    error: errorEmptyObject,
    userId: 'testUserId',
    saveCartName: 'testSaveCartName',
  }),
  new LoadWishListFail({
    cartId: 'testCartId',
    error: errorEmptyObject,
  }),
  new CancelReplenishmentOrderFail({
    message: 'error',
  }),
  new UnassignB2BUserUserGroupFail({
    error: errorEmptyObject,
    orgCustomerId: 'testOrgCustomerId',
    userGroupId: 'testUserGroupId',
  }),
  new AssignBudgetFail({
    budgetCode: 'testBudgetCode',
    error: errorEmptyObject,
  }),
  new LoadApprovalProcessesFail({
    error: errorEmptyObject,
  }),
  new LoadPermissionTypesFail({
    error: errorEmptyObject,
  }),
  new LoadUnitOrdersFail(errorEmptyObject),
  new LoadCmsComponentFail({
    error: errorEmptyObject,
    pageContext: { id: 'testPageId', type: PageType.CONTENT_PAGE },
    uid: 'testUid',
  }),
  new LoadCmsNavigationItemsFail('nodeId', errorEmptyObject),
  new LoadProductFail('productCode123', errorEmptyObject, 'scope'),
  new LoadUserConsentsFail(errorEmptyObject),
  new EntityFailAction('entityType', 'entityId', errorEmptyObject),
];

(screenshot: )
image

  1. VALID EMPTY STRING
const errorEmptyString = '';
export const actionsUsing_errorEmptyString = [
  new LoadCdcUserTokenFail({
    initialActionPayload: {
      baseSite: 'testBaseSite',
      idToken: 'testIdToken',
      signatureTimestamp: 'testSignatureTimestamp',
      UID: 'testUID',
      UIDSignature: 'testUIDSignature',
    },
    error: errorEmptyString,
  }),
  new CustomerSearchFail(errorEmptyString),
  new CartAddEntryFail({
    cartId: 'testCartId',
    error: errorEmptyString,
    productCode: 'testProductCode',
    quantity: 1,
    userId: 'testUserId',
    pickupStore: 'testPickupStore',
  }),
  new EditSavedCartFail({
    cartId: 'testCartId',
    error: errorEmptyString,
    userId: 'testUserId',
    saveCartName: 'testSaveCartName',
  }),
  new LoadWishListFail({
    cartId: 'testCartId',
    error: errorEmptyString,
  }),
  new CancelReplenishmentOrderFail({
    message: 'error',
  }),
  new UnassignB2BUserUserGroupFail({
    error: errorEmptyString,
    orgCustomerId: 'testOrgCustomerId',
    userGroupId: 'testUserGroupId',
  }),
  new AssignBudgetFail({
    budgetCode: 'testBudgetCode',
    error: errorEmptyString,
  }),
  new LoadApprovalProcessesFail({
    error: errorEmptyString,
  }),
  new LoadPermissionTypesFail({
    error: errorEmptyString,
  }),
  new LoadUnitOrdersFail(errorEmptyString),
  new LoadCmsComponentFail({
    error: errorEmptyString,
    pageContext: { id: 'testPageId', type: PageType.CONTENT_PAGE },
    uid: 'testUid',
  }),
  new LoadCmsNavigationItemsFail('nodeId', errorEmptyString),
  new LoadProductFail('productCode123', errorEmptyString, 'scope'),
  new LoadUserConsentsFail(errorEmptyString),
  new EntityFailAction('entityType', 'entityId', errorEmptyString),
];

(screenshot: )
image

@@ -196,12 +223,20 @@ export class LoadB2BUsers extends StateUtils.EntityLoadAction {
}

export class LoadB2BUsersFail extends StateUtils.EntityFailAction {
error: ErrorActionType = this.payload.error;
Copy link
Contributor Author

@Platonn Platonn Jun 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NOTE]
such lines are not needed in classes that extend from StateUtils.EntityFailAction. It's already done inside StateUtils.EntityFailAction super class

Comment on lines -57 to -60
interface CreateCartFailPayload extends CreateCartPayload {
error: ErrorActionType;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NOTE]

Removed this interface in favor of inline info about error:

  • CreateCartPayload & { error: any }
  • CreateCartPayload & { error: ActionErrorProperty }`

@@ -79,13 +89,28 @@ interface LoadWishListFailPayload {
* temporary cart used to track loading/error state or to normal wish list entity.
*/
cartId: string;
error: ErrorActionType;
error: ActionErrorProperty;
Copy link
Contributor Author

@Platonn Platonn Jun 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NOTE]

I didn't split the LoadWishListFailPayload, to keep benefiting from its useful existing JSDocs

Comment on lines 85 to 111
interface TypeOf_SetStoreDetailsFailure {
(props: { error: ActionErrorProperty }): {
error: ActionErrorProperty;
} & TypedAction<typeof STORE_DETAILS_FAIL>;

/**
* @deprecated Use the `error` parameter with a non-null, non-undefined value.
* Support for `null` or `undefined` will be removed in future versions,
* along with the feature toggle `ssrStrictErrorHandlingForHttpAndNgrx`.
*/
(props: { error: any }): { error: any } & TypedAction<
typeof STORE_DETAILS_FAIL
>;
}

// Note for future: when removing the old deprecated code, let's do the following:
// - remove `TypeOf_SetStoreDetailsFailure`
// - replace the implementation of `SetStoreDetailsFailure` with the following:
// ```
// export const SetStoreDetailsFailure = createAction(
// STORE_DETAILS_FAIL,
// props<{ error: ActionErrorProperty }>()
// );
// ```

export const SetStoreDetailsFailure: TypeOf_SetStoreDetailsFailure =
createAction(STORE_DETAILS_FAIL, props<{ error: any }>());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NOTE]

It's a single exceptional case where NgRx actions are not classes (with constructors), but factories created with the createAction ngrx util.

This exceptional case required an exceptional solution.

…| undefinied instead of any in deprecated constructor
Comment on lines -26 to -30
interface LoadUserTokenFailurePayload {
error: ErrorActionType;
initialActionPayload: LoadUserTokenPayload;
}

Copy link
Contributor Author

@Platonn Platonn Jun 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NOTE]

Removed in favor of defining initialActionPayload: LoadUserTokenPayload separately, and error: <specific_type> separately

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NOTE]

Moved within core lib. From /model/error-action.ts to error-handling/effects-error-handler/error-action.ts

Comment on lines +85 to +101
/**
* @deprecated Please use the `error` parameter with a non-null, non-undefined value.
* Support for `null` or `undefined` will be removed in future versions,
* along with the feature toggle `ssrStrictErrorHandlingForHttpAndNgrx`.
*/
constructor(
entityType: string,
id: EntityId,
// eslint-disable-next-line @typescript-eslint/unified-signatures -- needed to deprecate only the old constructor
error: any
);
/**
* @deprecated Please use the `error` parameter with a non-null, non-undefined value.
* The `error` parameter will become required in future versions,
* along with removing the feature toggle `ssrStrictErrorHandlingForHttpAndNgrx`.
*/
constructor(entityType: string, id: EntityId);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NOTE]

In this exceptional case I added 2 (but not 1) deprecated constructors, because:

  • error can be any
  • AND MOREOVER error can be not passed at all (as error? argument is optional)

Comment on lines +28 to +37
constructor(error: ActionErrorProperty);
/**
* @deprecated Please use the `error` parameter with a non-null, non-undefined value.
* Support for `null` or `undefined` will be removed in future versions,
* along with the feature toggle `ssrStrictErrorHandlingForHttpAndNgrx`.
*/
constructor(
// eslint-disable-next-line @typescript-eslint/unified-signatures -- for distinguishing deprecated constructor
error: any
);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NOTE]

Some ngrx actions were not refactored in the past PR https://github.com/SAP/spartacus/pull/17657/files from any to ErrorActionType.

So in this PR I'm refactoring them directly from any to ActionErrorProperty.

Note: I expect in the upcoming weeks in develop there might be more new ngrx actions with error: any that we should refactor analogically, before releasing our "Ssr Error Handling" epic

@pawelfras
Copy link
Contributor

Have you considered creating a separate ticket to track deprecations which eventually will be removed and attaching its ID to all related places?

STORE_DETAILS_FAIL,
props<{ error: ErrorActionType }>()
);
interface TypeOf_SetStoreDetailsFailure {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

query: What about simply calling it SetStoreDetailsFailure? Using TypeOf_ feels strange to me - not sure whether it's a common approach and I'm not familiar with it, but I'm happy to learn. Besides, it is possible to have the same name for const and interface/type. Interface won't be exported outside this file, so I guess it's not a problem to use the same name.

Copy link
Contributor Author

@Platonn Platonn Jul 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, TypeOf_ it looks odd, even to me. (... "odd even" 🙃).
It would be too bad if anyone gets inspired by this and copies it to other places.

I'll try your suggestion.

* Support for `null` or `undefined` will be removed in future versions,
* along with the feature toggle `ssrStrictErrorHandlingForHttpAndNgrx`.
*/
constructor(payload: { ownerKey: string; error: null | undefined });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

query: Is the order od constructor's overriding proper? Shouldn't the new, not deprecated definition, be first?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! will fix it

* Support for `null` or `undefined` will be removed in future versions,
* along with the feature toggle `ssrStrictErrorHandlingForHttpAndNgrx`.
*/
constructor(payload: { ownerKey: string; error: null | undefined });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

query: Is the order od constructor's overriding proper? Shouldn't the new, not deprecated definition, be first?

Copy link
Contributor Author

@Platonn Platonn Jul 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many thanks for a careful review. Good catch!

Hmm. it seems like I could not have saved and commited latest changes in this file.
Moreover, I can see null | undefined being used here, instead of any (but should be any).

*/
constructor(payload: { ownerKey: string; error: null | undefined });
constructor(
// eslint-disable-next-line @typescript-eslint/unified-signatures -- needed to deprecate only the old constructor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

query: Shouldn't the eslint-disable-next-line comment be used in a deprecated constructor? Or actually it doesn't matter? Nevertheless, it's different than in other places.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a natural consequence of the mistake you commented on there. it fill be fixed by fixing the mistake there

*/
constructor(payload: { ownerKey: string; error: null | undefined });
constructor(
// eslint-disable-next-line @typescript-eslint/unified-signatures -- needed to deprecate only the old constructor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

query: Shouldn't the eslint-disable-next-line comment be used in a deprecated constructor? Or actually it doesn't matter? Nevertheless, it's different than in other places.

*/
constructor(payload: { ownerKey: string; error: null | undefined });
constructor(
// eslint-disable-next-line @typescript-eslint/unified-signatures -- needed to deprecate only the old constructor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

query: Shouldn't the eslint-disable-next-line comment be used in a deprecated constructor? Or actually it doesn't matter? Nevertheless, it's different than in other places.

* Support for `null` or `undefined` will be removed in future versions,
* along with the feature toggle `ssrStrictErrorHandlingForHttpAndNgrx`.
*/
constructor(payload: { ownerKey: string; error: null | undefined });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

query: Is the order od constructor's overriding proper? Shouldn't the new, not deprecated definition, be first?

error: null | undefined,
scope?: string
);
constructor(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

query: Is the order od constructor's overriding proper? Shouldn't the new, not deprecated definition, be first?

* Note: Allowing for `null` or `undefined` will be removed in future versions
* together with the feature toggle `ssrStrictErrorHandlingForHttpAndNgrx`.
**/
constructor(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

query: Shouldn't the eslint-disable-next-line comment be used in a deprecated constructor? Or actually it doesn't matter? Nevertheless, it's different than in other places.

@pawelfras
Copy link
Contributor

During QA, I faced an error:
image
Probably due to missing unknown type in DeprecatedLoadWishListFailPayload

interface DeprecatedLoadWishListFailPayload
  extends Omit<LoadWishListFailPayload, 'error'> {
  error: null | undefined;
}

- put non-deprecated constructor before the deprecated one
- update outdated @deprecate JSdoc - to be more concise
- change `null | undefined` to `any` in @deprecated constructors
Copy link
Contributor

@pawelfras pawelfras left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👌

@Platonn
Copy link
Contributor Author

Platonn commented Jul 9, 2024

After re-thinking, the value in runtime can be anything unknown, so there is no sense in deprecating null | undefined, because it can be null or undefined anyway in runtime.

So closing in favor of #19036

@Platonn Platonn closed this Jul 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants