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

An unobvious point when developing a Button-or-Link component. Optional href for tag a and mandatory for Link from Next.js. [5.5.2] #58973

Closed
MrOxMasTer opened this issue Jun 22, 2024 · 14 comments

Comments

@MrOxMasTer
Copy link

MrOxMasTer commented Jun 22, 2024

🔎 Search Terms

Polymorphic Link/Button Components in React & TypeScript

🕗 Version & Regression Information

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.5.2#code/JYWwDg9gTgLgBAKjgQwM5wEoFNkGN4BmUEIcA5FDvmQNwBQdWAHpLHMAHYxZQF5ZwAQgFcYMCB0FosABWJh0AbzpxVcADbIARlnUAuOKhhROAc3pq4AN2QnkXAwCIwJkLYCejuAB84j1Fi4EgAmHl6+jtywwGE+fqEcpjyOFmrqEMjBZgD8BloQEOo4HKmq6ZlmACrMMLlw+YXF9AC+DDDuYAIAEpUAsgAyImISchAKcAC8cMqWABaUBHUcWFY8LXAAZJhUMAB0Q+IcPQMAgmImWqJYqAA8x4OihwCiRSBYXAB89HTtnXD3Jw4uFm0FG4ymMzU8ywBAMRhMiXWW2weD2gOB0AB52Al24twBQJBUBeWDen2+zFY8F+AgOI3k6CmdMk0jB6C2AAoCRioGy4vdmWyAJQUljQeBBDhGISPCSTOAcyFlbS6AA0KjUNjsXHVlnKWUSurSGQNpmqTBgRtUuxtLjGqDozQMgoZQsmH2mGtUwAICrtCl20IIbqVljglBgwigHDgN2Q0xtu39qGaH0Umh06maNwA9MgPl64M1SnBCxGozGbrjDnAaRNHNWJI5FInk804B9c42OF9HTQgA

💻 Code

In the playground

🙁 Actual behavior

Highlights an error with silly information

🙂 Expected behavior

So that an error is not highlighted, which also incorrectly indicates

Additional information about the issue

I can't make one component for the link and button depending on the href. Why does he think that the button is a link if I have a condition.

@MrOxMasTer MrOxMasTer changed the title The inability to create a single component for a button and a link depending on the href [5.5.2] The inability to create a single component for a button and a link depending on the href. Non-obvious compiler errors. [5.5.2] Jun 22, 2024
@MartinJohns
Copy link
Contributor

Please fill out the issue template completely.

Just checking for truthiness of props.href is not enough to narrow the type, because the string can be empty and thus falsy. In that case your props still can be typed HTMLAnchorProps in line 31, which has incompatible properties with <button>.

You can explicitly check for a string instead: typeof props.href === "string"

@MrOxMasTer
Copy link
Author

You can explicitly check for a string instead: typeof props.href === "string"

It works in playground, but it doesn't work in my project. I am using nextjs 14.2.4

image
image
image
image

@MrOxMasTer
Copy link
Author

But at the same time, I still have the old versions

image
image

@MrOxMasTer
Copy link
Author

I've updated and the error still hasn't gone away.
image
image
image

@MartinJohns
Copy link
Contributor

From your pictures it's not clear what your issue is, but nothing indicates a bug in TypeScript, just trouble using it, and this issue tracker is not suitable as a general help forum. Perhaps you should try StackOverflow or the TypeScript discord?

@MrOxMasTer
Copy link
Author

MrOxMasTer commented Jun 22, 2024

The chain of actions and the appearance of errors:

1 Problem:
First there is the props type of the regular button and the props type of the link component from Next.js:
image

My button is highlighted in red just like that...
image

Questions:
Why is the button highlighted in red if there is nothing superfluous except the "POSSIBLE" href?

Even if I do a restructuring, I still have a mistake:
image

I can fix this by making this predicate:
image

And all my mistakes disappear.:
image

But at the same time, I lose the normal typing of props "type":
image
image

Instead of the typical: "button" | "submit" | "reset" | undefined
I get the type: string | undefined

@MrOxMasTer
Copy link
Author

MrOxMasTer commented Jun 23, 2024

From your pictures it's not clear what your issue is, but nothing indicates a bug in TypeScript, just trouble using it, and this issue tracker is not suitable as a general help forum. Perhaps you should try StackOverflow or the TypeScript discord?

https://codesandbox.io/p/devbox/test-typescript-q89n2h The error is not immediately loaded, but if you touch the button, it will appear
image

@MartinJohns
Copy link
Contributor

Screenshots are a terrible way to describe your issue, because most information is not accessible.

Nothing here indicates a bug in TypeScript, just a lack of understanding of either the types you work with, or how narrowing works.

In your "NextJS" case the typeof check for string does not work, because the href property of HTMLLinkProps is typed string | UrlObject. So if you check only for string it can still be a UrlObject in the else-branch, and this means the type HTMLButtonProps | HTMLLinkProps can't be narrowed to HTMLButtonProps, resulting in incompatible properties for your <button> from the still remaining HTMLLinkProps type.

For these types you can just check for undefined, because either it's undefined (or missing) from the HTMLButtonProps, or it's string | UrlObject (but never undefined) from the HTMLLinkProps. So by checking for undefined you make sure your value is not a HTMLButtonProps.

@MrOxMasTer
Copy link
Author

MrOxMasTer commented Jun 23, 2024

For these types you can just check for undefined, because either it's undefined (or missing) from the HTMLButtonProps, or it's string | UrlObject (but never undefined) from the HTMLLinkProps. So by checking for undefined you make sure your value is not a HTMLButtonProps.

I originally had this check, which also caused an error. If it were that simple, I wouldn't be writing here.

You don't have the option to use another framework in playground. And then it was another problem, which was fixed in a different way

You told me exactly the opposite (that you need to check the href for "string"), despite the fact that I said that this is an unusual html link tag, a Link, which the screenshots prove. But even if you omit this point, it still causes an error If I correct for another check.

Once again, please go in for example and see that it still causes an error. I made 2 components with different checks. One specifically for undefined, and the other for the presence of this props in principle:
https://codesandbox.io/p/devbox/test-typescript-q89n2h

image
image

@MartinJohns
Copy link
Contributor

MartinJohns commented Jun 23, 2024

If your href property is undefined, then you're dealing with a HTMLButtonProps. In your second image you're trying to use HTMLButtonProps for the <Link> element, and vice versa HTMLLinkProps for the <button> element.

Either swap the elements, or check if href is not undefined: typeof props.href !== "undefined".

And just checking for truthyness of href like in your first image does not work, because it can be an empty string, which is falsy, but it's not enough to narrow the type.

@MrOxMasTer
Copy link
Author

MrOxMasTer commented Jun 23, 2024

Either swap the elements, or check if href is not undefined: typeof props.href !== "undefined".

Okay, I'll agree on that. I wrote the condition incorrectly because I was in a hurry.

Let's move on. Why do I lose button typing if I don't have an href?
image

https://codesandbox.io/p/devbox/test-typescript-q89n2h

Why did my type narrow down to the HTMLButtonProps type, then it should show me in "type" everything that fits the button.
I checked, ComponentProps<"button"> has these types

@MartinJohns
Copy link
Contributor

I'm sorry, but I'll drop out of this issue. Again, nothing you have shown here indicates a bug with TypeScript, and this is the wrong place for general support / for teaching language basics. The issue tracker is not meant as a support forum, it's for bugs with TypeScript and feature requests.

@MrOxMasTer
Copy link
Author

MrOxMasTer commented Jun 23, 2024

And just checking for truthyness of href like in your first image does not work, because it can be an empty string, which is falsy, but it's not enough to narrow the type.

Why does the question highlight to me the error of a ton of unnecessary text, but does not highlight the main one, that my UrlObject type does not fit the condition or string does not fit the condition or that I may have an empty one that does not fit or fits (again, to the reflection that string prevents me). Why is this the purpose of this tool, but it just doesn't perform this function to protect me from unnecessary types. It does, but what's the point of doing it as a dev tool if it helps the developer half and, conversely, confuses, with this error output

@MrOxMasTer
Copy link
Author

Thanks: learn the basics. Your task of the tool, as well as typing, is to protect against non-obvious moments and strange javascript typing, so that it would be more explicit. From unnecessary or incorrect types, but instead, on the contrary, it confuses me even more and does not help.
That's why I use your tool, so that there are no problems, but it seems exactly the opposite

@MrOxMasTer MrOxMasTer changed the title The inability to create a single component for a button and a link depending on the href. Non-obvious compiler errors. [5.5.2] An unobvious point when developing a Button-or-Link component. Optional href for tag a and mandatory for Link from Next.js. [5.5.2] Jun 23, 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

No branches or pull requests

2 participants