[React+Tailwind] Dropdown を TypeScript に書き直してみた | 心を無にして始める React

準備

書き直すベースはこちらの Dropdown コンポーネントです。

JavaScript

ベースの Dropdown.js です。

import { forwardRef } from 'react';
import { Dropdown as FlowbiteDropdown } from 'flowbite-react';

const Dropdown = forwardRef((
  {
    arrowIcon = true,
    children,
    floatingArrow = false,
    inline = false,
    label,
    ...otherProps
  },
  ref,
) => {
  return (
    <FlowbiteDropdown
      arrowIcon={arrowIcon}
      floatingArrow={floatingArrow}
      inline={inline}
      label={label}
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteDropdown>
  );
});

const DropdownDivider = (
  {
    ...otherProps
  },
) => {
  return (
    <FlowbiteDropdown.Divider
      {...otherProps}
    />
  );
};

const DropdownHeader = forwardRef((
  {
    children,
    ...otherProps
  },
  ref,
) => {
  return (
    <FlowbiteDropdown.Header
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteDropdown.Header>
  );
});

const DropdownItem = (
  {
    children,
    icon,
    onClick,
    ...otherProps
  },
) => {
  return (
    <FlowbiteDropdown.Item
      icon={icon}
      onClick={onClick}
      {...otherProps}
    >
      {children}
    </FlowbiteDropdown.Item>
  );
};

export default Object.assign(Dropdown, {
  Divider: DropdownDivider,
  Header: DropdownHeader,
  Item: DropdownItem,
});

TypeScript

Dropdown.tsx として編集します。

import { ComponentProps, forwardRef, LegacyRef } from 'react';
import {
  Dropdown as FlowbiteDropdown,
  DropdownProps as FlowbiteDropdownProps,
} from 'flowbite-react';

type DropdownProps = {} & FlowbiteDropdownProps

const Dropdown = forwardRef((
  {
    arrowIcon = true,
    children,
    floatingArrow = false,
    inline = false,
    label,
    ...otherProps
  }: DropdownProps,
  ref: LegacyRef<HTMLButtonElement>,
) => {
  return (
    <FlowbiteDropdown
      arrowIcon={arrowIcon}
      floatingArrow={floatingArrow}
      inline={inline}
      label={label}
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteDropdown>
  );
});

type DropdownDividerProps = {} & ComponentProps<typeof FlowbiteDropdown.Divider>

const DropdownDivider = (
  {
    ...otherProps
  }: DropdownDividerProps,
) => {
  return (
    <FlowbiteDropdown.Divider
      {...otherProps}
    />
  );
};

type DropdownHeaderProps = {} & ComponentProps<typeof FlowbiteDropdown.Header>

const DropdownHeader = forwardRef((
  {
    children,
    ...otherProps
  }: DropdownHeaderProps,
  ref: LegacyRef<HTMLDivElement>,
) => {
  return (
    <FlowbiteDropdown.Header
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteDropdown.Header>
  );
});

type DropdownItemProps = {} & ComponentProps<typeof FlowbiteDropdown.Item>

const DropdownItem = (
  {
    children,
    icon,
    onClick,
    ...otherProps
  }: DropdownItemProps,
) => {
  return (
    <FlowbiteDropdown.Item
      icon={icon}
      onClick={onClick}
      {...otherProps}
    >
      {children}
    </FlowbiteDropdown.Item>
  );
};

export default Object.assign(Dropdown, {
  Divider: DropdownDivider,
  Header: DropdownHeader,
  Item: DropdownItem,
});

結果

変化はないので、前と同じ。

はい、できました。