在 Typescript 中反应子组件

Ste*_*ven 2 typescript reactjs

我们有一些复杂的组件组合,我在使它们类型安全时遇到了麻烦。根据下面的代码,我希望 Typescript 能够为Menu.Itemor提供类型Menu.Link,但由于某种原因它不能提供类型,它们被推断为“任何”(JSX.Element<any>当您将其包装在 JSX 中时会进行改进。知道为什么会这样吗?

import * as React from 'react';

type RootFunctionComponent<OwnProps, SubComponents> = React.FunctionComponent<OwnProps> & SubComponents;

interface ItemProps {
    text: string;
};

interface LinkProps {
    href: string;
}

const Item: React.FunctionComponent<ItemProps> = props => <div {...props} />;
const Link: React.FunctionComponent<LinkProps> = props => <div {...props} />;

interface MenuSubComponents {
    Item: React.FunctionComponent<;
    Link: typeof Link;
}

const Menu: React.FunctionComponent<{}, MenuSubComponents> & MenuSubComponents = props => <div {...props} />

Menu.Item = Item;
Menu.Link = Link;


const Test: React.FunctionComponent<{}> = () => {
    return <>
        <Menu>
            <Menu.Item text={false} />
            <Menu.Link />
        </Menu>
    </>
}

Run Code Online (Sandbox Code Playgroud)

结果:

产生的任何类型

小智 5

问题在于菜单类型定义:

React.FC<{}, MenuSubComponents>
Run Code Online (Sandbox Code Playgroud)

正确的用法是:

React.FC<MenuSubComponents>
Run Code Online (Sandbox Code Playgroud)

你可以在这里看到这个:https : //codesandbox.io/s/condescending-lamarr-xjkcw


小智 3

这是带有 props 的高阶组件表的完整示例

import React from 'react'
import { tw } from 'twind'

import Body from './Body'
import Cell from './Cell'
import Head from './Head'
import Row from './Row'

export type CommonPropsType = {
  className?: string
  children: React.ReactNode
}

type TableSubComponents = {
  Row: typeof Row
  Cell: typeof Cell
  Head: typeof Head
  Body: typeof Body
}

type TablePropsType = CommonPropsType & { wrapperClassName?: string }

const Table: React.FunctionComponent<TablePropsType> & TableSubComponents = (
  props: TablePropsType
) => {
  const { className, children, wrapperClassName } = props
  return (
    <div className={tw('overflow-x-auto pb-2', wrapperClassName)}>
      <table
        className={tw('min-w-full leading-normal', className)}
        cellPadding="8">
        {children}
      </table>
    </div>
  )
}

Table.Row = Row
Table.Cell = Cell
Table.Head = Head
Table.Body = Body

export default Table
Run Code Online (Sandbox Code Playgroud)