在箭头函数中将 JavaScript 对象解构转换为 Typescript

Converting JavaScript object destructuring to Typescript in arrow function

我已将以下箭头函数解构转换为 Typescript,但我不明白如何解释最后一项:icon:Icon。此项目未进口或申报。

原文JavaScript:

const NavbarDropdown = ({
  children,
  count,
  showBadge,
  header,
  footer,
  icon: Icon
}) => (
  <UncontrolledDropdown nav inNavbar className="mr-2">
    <DropdownToggle nav className="nav-icon dropdown-toggle">
      <div className="position-relative">
        <Icon className="align-middle" size={18} />

已转换为 TypeScript,但 {icon: Icon} 出现错误,其中 Icon 既未导入也未在函数体内以外的任何地方声明:

const NavbarDropdown = (
    {children} : {children: string},
    {count} : {count: number},
    {showBadge} : {showBadge: boolean},
    {header} : { header: string},
    {footer} : { footer: string},
    {icon: Icon},
  ) => (
    <UncontrolledDropdown nav inNavbar className="mr-2">
      <DropdownToggle nav className="nav-icon dropdown-toggle">
        <div className="position-relative">
          <Icon className="align-middle" size={18} />

更新:我明白这个小组所指的关于 Icon/icon 的内容,但我仍然找不到导入或声明图标的任何地方。正如此处所建议的那样,是 NavbarDropdown 调用的代码片段:

  <Collapse navbar>
    <Nav className="ml-auto" navbar>
      <NavbarDropdown
        header="New Messages"
        footer="Show all messages"
        icon={MessageCircle}
        count={messages.length}
        showBadge
      >
        {messages.map((item, key) => {
          return (
            <NavbarDropdownItem
              key={key}
              icon={
                <img
                  className="avatar img-fluid rounded-circle"
                  src={item.avatar}
                  alt={item.name}
                />
              }
              title={item.name}
              description={item.description}
              time={item.time}
              spacing
            />
          );
        })}
      </NavbarDropdown>

两个似乎很突出的问题:

  1. 你的问题 Icon

  2. 这不是定义单个解构参数类型的方式

回复#1,你说:

Converted to TypeScript except an error with {icon: Icon} where Icon is neither imported nor declared anywhere except within the body of the function

在JavaScript版本中,icon/Icon看起来像这样:

const NavbarDropdown = ({
  children,
  count,
  showBadge,
  header,
  footer,
  icon: Icon
}) => (

icon: Icon看起来很像 TypeScript 类型,但事实并非如此。这是解构的一部分。它采用 object 上 icon 属性 的值并将其分配给 Icon 标识符。就好像你有这个:

const NavbarDropdown = (props) => {
    let children = props.children;
    // ...
    let Icon = props.icon;

所以函数中用于它的标识符以大写字符开头,因此它可以用作 JSX 中的 React 组件:<Icon className="align-middle" size={18} />(如果你有 <icon .../>,它会是 HTML 元素,而不是 React 组件。)

回复 #2:您的代码 id 解构了一系列参数,每个参数一个 属性。相反,您将类型放在解构 {}s:

之后
const NavbarDropdown = ({
  children,
  count,
  showBadge,
  header,
  footer,
  icon: Icon
}: {
  children: string;
  count: number;
  showBadge: boolean;
  header: string;
  footer: string;
  icon: React.Component;
}) => (
  <UncontrolledDropdown nav inNavbar className="mr-2">
    <DropdownToggle nav className="nav-icon dropdown-toggle">
      <div className="position-relative">
        <Icon className="align-middle" size={18} />
        ...

或者声明一个可以重用的类型(这也可能有助于清晰),然后使用该类型名称:

interface NavbarDropdownProps {
  children: string;
  count: number;
  showBadge: boolean;
  header: string;
  footer: string;
  icon: React.Component;
}
const NavbarDropdown = ({
  children,
  count,
  showBadge,
  header,
  footer,
  icon: Icon
}: NavbarDropdownProps) => (
  <UncontrolledDropdown nav inNavbar className="mr-2">
    <DropdownToggle nav className="nav-icon dropdown-toggle">
      <div className="position-relative">
        <Icon className="align-middle" size={18} />
        ...

但特别是在键入 React 功能组件时,React 提供了一个有用的类型:React.FunctionComponent 或其更短的别名 React.FC(大多数人使用后者):

interface NavbarDropdownProps {
  children: string;
  count: number;
  showBadge: boolean;
  header: string;
  footer: string;
  icon: React.Component;
}

const NavbarDropdown: React.FC<NavbarDropdownProps> = ({
  children,
  count,
  showBadge,
  header,
  footer,
  icon: Icon
}) => (
  <UncontrolledDropdown nav inNavbar className="mr-2">
    <DropdownToggle nav className="nav-icon dropdown-toggle">
      <div className="position-relative">
        <Icon className="align-middle" size={18} />
        ...

请注意,由于您是通过 React.FC 使用通用参数来告诉 TypeScript 道具的类型,因此您不必再在参数列表中提供类型。

但正常情况下,功能组件中的children应该是ReactNode类型,而不是stringstring 会起作用,因为 ReactNode 是一个联合类型,而 string 是它的一部分,但它会缩小 children 的类型,通常你希望允许完整的children.

的范围