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

[Question] Accept only one child of specific set of types #271

Closed
PedroBern opened this issue Aug 20, 2020 · 7 comments
Closed

[Question] Accept only one child of specific set of types #271

PedroBern opened this issue Aug 20, 2020 · 7 comments
Assignees
Labels
good first issue Good for newcomers

Comments

@PedroBern
Copy link

Question

How to have a component that accepts only one child, of a specific set of types?

What I need

To accept one child of one of the following types (React Native):

  • Animated.FlatList
  • Animated.SectionList
  • Animated.ScrollView

What I have tried

Attempt 1

type ChildrenProps =
  | Animated.AnimatedProps<ScrollView>
  | Animated.AnimatedProps<SectionList>
  | Animated.AnimatedProps<FlatList>
  | SectionList['props']
  | FlatList['props']
  | ScrollView['props']

interface Props {
  children: React.ReactElement<ChildrenProps>
}

const MyComponent: React.FunctionComponent<Props> ...

Attempt 2

interface Props { 
children:
    | React.ReactElement<Animated.AnimatedComponent<typeof ScrollView>>
    | React.ReactElement<Animated.AnimatedComponent<typeof SectionList>>
    | React.ReactElement<Animated.AnimatedComponent<typeof FlatList>>
}

const MyComponent: React.FunctionComponent<Props> ...

Result

Either way, my component ends up accepting any kind of Children.

Bonus

If this is solved, how would I have a new prop, that accepts prop of the specific type? For example:

interface Props { 
children: ... // above
childrenProps: ... // (?) if FlatList, accept only props of FlatList, if ScrollView...
}
@PedroBern PedroBern added the good first issue Good for newcomers label Aug 20, 2020
@swyxio
Copy link
Collaborator

swyxio commented Aug 20, 2020

I believe @ferdaber worked on your bonus question with Ryan Florence and the conclusion was it couldn't be done yet.

you could view this as a bad thing, but personally I view it as typescript discouraging you from designing implicit/polymorphic apis like this.

i haven't tried it but for the main question, how about typing children as a tuple - [ReactNode, never] etc

@ferdaber
Copy link
Collaborator

You can type the structure of your children: just one child, or a tuple of children. The thing you cannot do is specify which component the children are.

The following are valid:

type OneChild = React.ReactElement
type TwoChildren = [React.ReactElement, React.ReactElement]
type ArrayOfProps = SomeProp[]
type NumbersChildren = number[]
type TwoNumbersChildren = [number, number]

This, however, will not work the way you want:

type MyComponentProps = { foo: string }
type MyComponentProps2 = { bar: boolean }

type OneChildOfSpecificComponentType = React.ReactElement<MyComponentProps>
type ChildrenOfSpecificComponentTypes = (
	| React.ReactElement<MyComponentProps> 
	| React.ReactElement<MyComponentProps2>
)[]

This is because when you write a JSX expression (const foo = <MyComponent foo='foo' />), the resultant type is blackboxed into a generic JSX.Element type.

@swyxio
Copy link
Collaborator

swyxio commented Aug 20, 2020

@ferdaber just curious, with the new "jsx runtime" that react 17 is bringing, any thoughts on whether that might change? the signature looks the same, so i doubt it, but figured its worth flagging to you incase you hadnt already considered it

@PedroBern the good news is you could always check the type of child as a runtime check and error early. dont let TS' inability to check it stop you.

@ferdaber
Copy link
Collaborator

The JSX runtime I don't think is coming for a while (it's still in the React RFCs phase). I have been monitoring it closely but mostly it will just affect the transpilation semantics on the TypeScript side: a change that will need to be done by their team. The types themselves wouldn't change and unfortunately we also won't get this specific issue fixed because of it :(

@swyxio
Copy link
Collaborator

swyxio commented Aug 20, 2020

thanks - @PedroBern pls reopen if any further q's!

@Sebastian-Nielsen
Copy link

@sw-yx , this issue was created 2 years ago, do you happen to know if it is still not possible? Are they at least considering supporting this?

@adiba
Copy link

adiba commented Jan 25, 2023

@Sebastian-Nielsen @sw-yx

See this stackoverflow question, which links to this GitHub issue, which is still open!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

5 participants