#Property 'href' does not exist on type
1 messages · Page 1 of 1 (latest)
Preview:```ts
import React, {ElementType, ReactNode} from "react"
type TagPropsMap = {
a: JSX.IntrinsicElements["a"]
button: JSX.IntrinsicElements["button"]
}
type TagsUnionType = {
[K in keyof TagPropsMap]: TagPropsMap[K] & {
as: K
buttonType?: "primary" | "second
...```
Okay my colleague mentioned me that the issue is that when I was spreading props, it lost it's original type
Here a fixed version:
Preview:```ts
import React, {ElementType, ReactNode} from "react"
type TagPropsMap = {
a: JSX.IntrinsicElements["a"]
button: JSX.IntrinsicElements["button"]
}
type TagsUnionType = {
[K in keyof TagPropsMap]: TagPropsMap[K] & {
as: K
buttonType?: "primary" | "second
...```
Preview:```ts
import React, {ElementType, ReactNode} from "react"
interface RoundedButtonBaseProps {
buttonType?: "primary" | "secondary"
semiActive?: boolean
}
interface RoundedButtonAProps
extends RoundedButtonBaseProps,
React.HTMLAttributes<HTMLAnchorElement>
...```
this should be the exact samething, but is a bit cleaner imo
That's nice too, but I shared a minimal example.
And I'm actually moving away from that. Since I did not enjoy having 10+ interfaces lying around in my file. And I wanted a way to compress it.
¯_(ツ)_/¯
sometimes it's better to have a more code that is easy to read than less code that is quite harder to read
but yeah, sounds like your component is doing a lot of different things then
which can sometimes be a sign of bad design
,I agree, some times it's better to have more code, but my use case is quite specific and I can't do much about it.
I do have one more question if you don't mind.
sure
Is there a way to make it so, that the as property has a default value and optional? in this 👆example?
don't think so
you cannot defined default values in interfaces
so that would need to be done in the parameters definion or in the function body
I was trying to do something like this, but as is still required even when it's undefined
type TagPropsMap = {
a: JSX.IntrinsicElements['a'] & { href: string };
button: JSX.IntrinsicElements['button'];
default: JSX.IntrinsicElements['button'];
link: LinkProps;
};
type TagsUnionType = {
[K in keyof TagPropsMap]: TagPropsMap[K] & {
as: K extends `default` ? undefined : K;
buttonType?: 'primary' | 'secondary';
children: ReactNode;
className?: string;
semiActive?: boolean;
};
}[keyof TagPropsMap];
problem with doing that inside of the parameters definition is that you could provide attributes for one memeber of the enum, then adding the default value would make the whole object incoherent (like passing href a nd defaulting to <button>)
I was trying to do something like this, but as is still required even when it's undefined
undefinedis different from optional
if you want to make it optional, use ?
Oh yeah, I need to use ? instead of just undefined 🤦♂️
unless you have https://www.typescriptlang.org/tsconfig#exactOptionalPropertyTypes enabled
but would not recommend it
From allowJs to useDefineForClassFields the TSConfig reference includes information about all of the active compiler flags setting up a TypeScript project.
So, if I do
type TagsUnionType = {
[K in keyof TagPropsMap]: TagPropsMap[K] & {
as?: K extends `default` ? undefined : K;
buttonType?: 'primary' | 'secondary';
children: ReactNode;
className?: string;
semiActive?: boolean;
};
}[keyof TagPropsMap];
The, component is not falling back to use the button type, and instead allows me to put any prop
the same way "" and null are two different things, the same way undefined and null mean different things and have different use-cases
that's why I recommend not using that syntax
it's unclear what the code is doing
which property is required for which value, etc
just use a union where each possibility is clearly laid out
¯_(ツ)_/¯