1

There's probably an obvious answer to this, but I haven't been able to identify the right keywords to find it.

Suppose I have a type-parameterized FooProps, e.g.:

type FooProps<T> = { ... bar: T, ...}

I'm building a FunctionComponent that should take a FooProps as its type parameter.

The following is not correct:

const component: FunctionComponent<PropsWithChildren<FooProps<T>>> = <T, >(props: FooProps<T>) => {...}

because cannot find name 'T'.

However,

const component: FunctionComponent<PropsWithChildren<FooProps>> = <T, >(props: FooProps<T>) => {...}

is not correct, because Generic type 'FooProps' requires 1 type argument(s).

I can get away with just not annotating it, but the inferred type is then <T>(props: FooProps<T>) => JSX.Element, which wouldn't be so bad, except it means that I have to include the children member manually on FooProps<T>.

What is the correct way to annotate the type of this FunctionComponent when the type that satisfies its type parameter has its own parameterization?


Follow-on question:

Okay, so the first issue is that component's props parameter is still declared as FooProps<T> rather than PropsWithChildren<FooProps<T>>. Correcting that gets me most of the way there. However, I'd still like to be a bit more explicit if I can.

So I can do:

const component: FunctionComponent<PropsWithChildren<FooProps<any>>> =
    <T, >(props: PropsWithChildren<FooProps<T>>) => {

but can't do:

const component: FunctionComponent<PropsWithChildren<FooProps<T>>> =
    <T, >(props: PropsWithChildren<FooProps<T>>) => {

Is there a way to do this explicitly so that the generic type can feed through all the way? In my particular use case, I don't actually use T directly in this component, so marking it any is fine, but it'd be nice to know I can be explicit if I need to.

Tiercelet
  • 147
  • 8

1 Answers1

1

It is perfectly fine to wrap your FooProps into PropsWithChildren:

import React, { PropsWithChildren } from 'react'


type FooProps<T> = { bar: T, }

const Component = <T,>(props: PropsWithChildren<FooProps<T>>) => {
  return null

}

const foo = <Component bar={1}>123</Component>

Playground

Your example does not work because you are trying to mix argument inference with explicit type declaration up front.

If you want to use generics, you are not allowed to use explicit type anymore. Using explicit type disabling type inference. Further more, using explicit type) means that you know all your types up front.

  • [This](https://stackoverflow.com/questions/68757395/how-to-make-a-functional-react-component-with-generic-type/68757498#68757498) answer might be useful – captain-yossarian from Ukraine Aug 20 '22 at 13:34
  • 1
    I was a little confused by "mix argument inference with explicit type declaration" then realized that I was still declaring `Props` as `T` rather than `PropsWithChildren`. Annotating the component's props correctly will get me most of what I want, but I'm going to add a follow-on syntax question too. Thanks! – Tiercelet Aug 22 '22 at 13:49