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

Derive props from $ type #1

Open
kylpo opened this issue Jun 7, 2022 · 4 comments
Open

Derive props from $ type #1

kylpo opened this issue Jun 7, 2022 · 4 comments
Labels
help wanted Extra attention is needed

Comments

@kylpo
Copy link
Contributor

kylpo commented Jun 7, 2022

I spent a few hours trying to figure this out, but without some way of defaulting a generic for an interface, I don't know if this is possible. This is possible for a function, but I wasn't able to get it for an interface (which is what we need when adding our primitives to the IntrinsicElements interface.

// Does NOT compile
type PrimitiveProps<T extends keyof JSX.IntrinsicElements> = React.ComponentProps<T> & {
  $: T = "div" // Error: A type literal property cannot have an initializer.ts(1247)
}

// Compiles, but errors when primitives have any non-`"img"` `$` value
type Prim<T extends keyof JSX.IntrinsicElements = "img"> =
  React.ComponentProps<T> & {
  $?: T
}

// in jsx...
<flex
  $="img"
  src="hello"
  notAnImgProp // correctly shows error 😃!
/>

<flex
  $="main" // incorrectly errors with `Type '"main"' is not assignable to type '"img"'` 😞 
/>
@kylpo kylpo added the help wanted Extra attention is needed label Apr 11, 2023
@kylpo
Copy link
Contributor Author

kylpo commented Apr 11, 2023

I believe the problem is that IntrinsicElements does not support a generic. If it did, we'd be able to infer its value (or use its default) based on how the generic is used (in the $: T)

type IntrinsicElement = keyof JSX.IntrinsicElements;

interface Primitive<T extends IntrinsicElement> extends JSX.IntrinsicElements[T] {
  $: T
}

declare global {
  namespace JSX {
    interface IntrinsicElements<T extends  IntrinsicElement> {
      flex: Primitive<T>
    }
  }
}

Buut, adding a generic to IntrinsicElements basically breaks all jsx types. A search on all of github for "interface IntrinsicElements<" reveals no hits. I don't think anyone has found a way to make this work. Perhaps an Issue on the TS github repo is in order?

Maybe microsoft/TypeScript#14729 will help?

@kylpo
Copy link
Contributor Author

kylpo commented Apr 11, 2023

For now, I'll leave $ and $- props untyped. If we want these props to be properly typed, we'll need to make proper <Flex> components that must be imported, but also can enforce their types. Much like https://dev.to/fabiobiondi/create-a-react-typescript-generic-component-2dal

@kylpo
Copy link
Contributor Author

kylpo commented Apr 22, 2023

I was excited to see this new feature in TS, but it is not what I need.

I should try to PR Typescript to add a root level generic to IntrinsicElements. Maybe these PRs (added in the recent TS version) will help?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

1 participant