In prop passing through children, how to align type to it

50 Views Asked by At

Problem: when I use below expression, IDE alerts typescript syntax error. I think typescript expects children to be assigned as ReactNode not as Array<object>.

----/page.tsx/----
...
<TopBar>{[
    {text:"career",href:"",class:"p-0 m-0"},
    {text:"contact",href:"",class:"p-0 m-0"},
    {text:"patient registry",href:"/patient_registry",class:"custom-outline p-1 rounded-2xl px-4 hover:bg-black hover:text-white"}
]}</TopBar>
...
----------------

----/TopBar.tsx/----
export default function TopBar({children}:Array<object>){//<-SYNTAX ERROR
    const menus:Array<ReactNode> = [];
    children.forEach((element:object,index:number)=>{
        menus.push(<Link key={index} className={element.class} href={element.href}>{element.text}</Link>);
    });
    return(
    <div className={"pl-4 pr-16 flex items-center h-16 w-screen justify-between border-b-gray-200 border-2 fixed bg-white z-10"}>
        <ImgBlock src={"/assets/svg/logo.png"} width={"7rem"} height={"4rem"}/>
        <div className={"flex gap-8 items-center"}>
            {menus}
        </div>
    </div>
    );
}
----------------

React.js works fine with @ts-ignore, but I can't stand red underline in my source code. Tell me the syntax to solve this problem.

3

There are 3 best solutions below

0
On BEST ANSWER

The destructure semantic of:

const { children }: Array<object> = [];

Is equivalent to:

const props: Array<object> = [];

const { children } = props;
// or const children = props.children;

The error makes sense since the property children does not really exist in the array type, as they are not a ReactProps object.

To fix it, what we need is just wrapping the original type with an object, and add a key with key name children with your required typing.

type TopBarProps = {
  children: object[],
}

// approach 1. using the destructure syntax
const TopBar = ({ children }: TopBarProps) => {
  useEffect(() => {
    children.forEach(() => {
      // no error
    });
  }, []);
}

// approach 2. using the accessor operator
const TopBar2 = (props: TopBarProps) => {
  const children = props.children;

  useEffect(() => {
    children.forEach(() => {
      // no error
    });
  }, []);
}
0
On
export default function TopBar({ children }: { children: Array<object> }) {
0
On

Thanks of all! I just edit my code like this:

interface ElementType {text:string,class:string,href:string}
export default function TopBar({children}:{children:Array<ElementType>}){
    const menus:Array<ReactNode> = [];
    children.forEach((element:ElementType,index:number)=>{
        menus.push(<Link key={index} className={element.class} href={element.href}>{element.text}</Link>);
    });
    return(
    <div className={"pl-4 pr-16 flex items-center h-16 w-screen justify-between border-b-gray-200 border-2 fixed bg-white z-10"}>
        <ImgBlock src={"/assets/svg/logo.png"} width={"7rem"} height={"4rem"}/>
        <div className={"flex gap-8 items-center"}>
            {menus}
        </div>
    </div>
    );
}