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

Specify ErrorResponse as interface to provide obvious contract #10876

Merged
merged 5 commits into from
Sep 27, 2023

Conversation

sgrishchenko
Copy link
Contributor

There is problem in current declaration of ErrorResponse: the private field leaks to the public contract. So ErrorResponse type behaves very strange on usage (see playground).
I propose to simplify the declaration of ErrorResponse and declare it's public interface obviously.

@changeset-bot
Copy link

changeset-bot bot commented Sep 16, 2023

🦋 Changeset detected

Latest commit: 6a0543f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@remix-run/router Patch
react-router Patch
react-router-dom Patch
react-router-dom-v5-compat Patch
react-router-native Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@remix-cla-bot
Copy link
Contributor

remix-cla-bot bot commented Sep 16, 2023

Hi @sgrishchenko,

Welcome, and thank you for contributing to React Router!

Before we consider your pull request, we ask that you sign our Contributor License Agreement (CLA). We require this only once.

You may review the CLA and sign it by adding your name to contributors.yml.

Once the CLA is signed, the CLA Signed label will be added to the pull request.

If you have already signed the CLA and received this response in error, or if you have any questions, please contact us at hello@remix.run.

Thanks!

- The Remix team

@remix-cla-bot
Copy link
Contributor

remix-cla-bot bot commented Sep 16, 2023

Thank you for signing the Contributor License Agreement. Let's get this merged! 🥳

@sgrishchenko
Copy link
Contributor Author

sgrishchenko commented Sep 21, 2023

The first point is that with my changes, you don't need 3-line comment about interface/implementation pattern. Now code is self-documented.

The second point: in the comment I removed there was the statement:

but we do want to export the shape so folks can build their own abstractions around instances

And your example perfectly demonstrates that with logError function. But what if I want to write unit test for logError? I will end up with force type casting or something like that:

logError({
  status: 400, 
  statusText: 'bad request',
  data: undefined,
} as ErrorResponse)

https://www.typescriptlang.org/play?noUncheckedIndexedAccess=true&exactOptionalPropertyTypes=true&ts=5.1.6#code/JYWwDg9gTgLgBAb2AZwEoQK4wKYFEpTSrbKQB2y2ANHPoVMaRBdXAKoByAygIIBiuAPp0iJcpQCS4ADYBfOADNCIOACIAAlGwhgADwC0UDGQD0hLNiiqAULZMm4AeTLSAnnBgALbHGBkcUGQAhtLIcBAKHt6KUEEg2ADu0ADWcMiemNIAJnAARj4AxlpBMH4A5lEk2NbS2PBaTCxwALxwZIns3PxCIgxizJIyABQALAAMYzQA5LlBOVoAjhgkMFM0CGkQ8QBccFNZJUFTcLIAlADcdg4SZHAYlFD60kFkWTSumGkZGNl5PjCuMDYfTBAgQBLlazASJDFDoCy9RjibBDBrI06nRDWOBwaQQMq9VH9FgXayyK5wHivO7IcqVOBgDC5aTAAoeQE+IJhdrYLK86wKYwFUrMXH4wnYXaI4mUTEIbFwAoDCC1AB0eLKQ2wquQMBK9xo2t1+uQABVsLoYIbVQc9aSFfY4AAFKDAABuJR8CmA2F+WQgJDaEHgtSCyQV2r8AWC0jJFIkcASL3gMAgcBAYf+nhQipC0l8t2MwBTKzgNXFYKgQ3lOONMHuu3GkzLtb19bNFpguxmczgi2WurWCttQV2xj53vabzJpwpACEsHAEwUXlMrZsl3BPEE3f800CoApoPF2UDc7rIRrCTW0m2G3AmzQFXX7ubLd3ZvNsEsVkOcSOx1ebBJ15KgyTgLlaErJEBmwU4gA

And the third point: with the current declaration, I don't see the public contract of ErrorResponse and what data I can use from it. To get this information, I need to investigate the code from internal implementation of UNSAFE_ErrorResponseImpl and I think it is conceptually wrong.

Copy link
Contributor

@brophdawg11 brophdawg11 left a comment

Choose a reason for hiding this comment

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

Thank you - the unit test is a great use-case for why we should make the change. I was just concerned that this was something being used incorrectly in app-code 👍

you don't need 3-line comment about interface/implementation pattern. Now code is self-documented.

Eh - "Self documenting code" is a buzzword I've seen abused too much over the years. Code describes "what"/"how", comments describe "why". Removing this comment is detrimental because we lose the reason for why we keep the interface and class separate in the first place.

packages/router/utils.ts Outdated Show resolved Hide resolved
@brophdawg11
Copy link
Contributor

@sgrishchenko Do you mind rebasing this and repointing it to dev since it contains code changes?

@sgrishchenko
Copy link
Contributor Author

sgrishchenko commented Sep 21, 2023

Ok, probably I'm wrong with the point that the comment is unnecessary anymore. I returned the comment back.
Of course, I will rebase my branch, no problem.
What do you mean by "reporting to dev"? I never did it before. Is there some guide for it or something like that?

@sgrishchenko
Copy link
Contributor Author

Oh, you mean dev branch? if so, I will do it, no problem.

@sgrishchenko sgrishchenko changed the base branch from main to dev September 21, 2023 16:49
@@ -1533,11 +1533,21 @@ export const redirectDocument: RedirectFunction = (url, init) => {
return response;
};

export interface ErrorResponse {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we keep this as a type to avoid changing the semantics to interface?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, we can, but from my point of view it exposes the public API, so it is exactly an interface semantically, or am I missing something? Maybe you want to avoid interface merging?

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, we prefer type over interface unless we need the ability for end users to augment the interface, which we shouldn't in this case

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@brophdawg11 brophdawg11 merged commit b98e82d into remix-run:dev Sep 27, 2023
3 checks passed
@github-actions
Copy link
Contributor

🤖 Hello there,

We just published version 6.17.0-pre.0 which includes this pull request. If you'd like to take it for a test run please try it out and let us know what you think!

Thanks!

@github-actions
Copy link
Contributor

🤖 Hello there,

We just published version 6.17.0 which includes this pull request. If you'd like to take it for a test run please try it out and let us know what you think!

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants