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

準備

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

JavaScript

ベースの Sidebar.js です。

import React, { forwardRef } from 'react';
import {
  Sidebar as FlowbiteSidebar,
} from 'flowbite-react';

const Sidebar = forwardRef((
  {
    children,
    collapseBehavior,
    collapsed,
    ...otherProps
  },
  ref,
) => {
  return (
    <FlowbiteSidebar
      collapseBehavior={collapseBehavior}
      collapsed={collapsed}
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteSidebar>
  );
});

const SidebarCollapse = forwardRef((
  {
    active = false,
    as,
    children,
    href,
    icon,
    label,
    labelColor,
    ...otherProps
  },
  ref,
) => {
  return (
    <FlowbiteSidebar.Collapse
      active={active}
      as={as}
      href={href}
      icon={icon}
      label={label}
      labelColor={labelColor}
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteSidebar.Collapse>
  );
});

const SidebarCTA = forwardRef((
  {
    children,
    color,
    ...otherProps
  },
  ref,
) => {
  return (
    <FlowbiteSidebar.CTA
      color={color}
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteSidebar.CTA>
  );
});

const SidebarItems = forwardRef((
  {
    children,
    ...otherProps
  },
  ref,
) => {
  return (
    <FlowbiteSidebar.Items
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteSidebar.Items>
  );
});

const SidebarItemGroup = forwardRef((
  {
    children,
    ...otherProps
  },
  ref,
) => {
  return (
    <FlowbiteSidebar.ItemGroup
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteSidebar.ItemGroup>
  );
});

const SidebarItem = forwardRef((
  {
    active = false,
    as,
    children,
    href,
    icon,
    label,
    labelColor,
    ...otherProps
  },
  ref,
) => {
  return (
    <FlowbiteSidebar.Item
      active={active}
      as={as}
      href={href}
      icon={icon}
      label={label}
      labelColor={labelColor}
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteSidebar.Item>
  );
});

const SidebarLogo = forwardRef((
  {
    children,
    className,
    href,
    img,
    imgAlt,
    ...otherProps
  },
  ref,
) => {
  return (
    <FlowbiteSidebar.Logo
      className={className}
      href={href}
      img={img}
      imgAlt={imgAlt}
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteSidebar.Logo>
  );
});

export default Object.assign(Sidebar, {
  Collapse: SidebarCollapse,
  CTA: SidebarCTA,
  Item: SidebarItem,
  ItemGroup: SidebarItemGroup,
  Items: SidebarItems,
  Logo: SidebarLogo,
});

TypeScript

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

import React, { ComponentProps, forwardRef } from 'react';
import {
  Sidebar as FlowbiteSidebar,
  SidebarProps as FlowbiteSidebarProps,
} from 'flowbite-react';
import { LegacyRef } from 'react';

type SidebarProps = {} & FlowbiteSidebarProps;

const Sidebar = forwardRef((
  {
    children,
    collapseBehavior,
    collapsed,
    ...otherProps
  }: SidebarProps,
  ref: LegacyRef<HTMLDivElement>,
) => {
  return (
    <FlowbiteSidebar
      collapseBehavior={collapseBehavior}
      collapsed={collapsed}
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteSidebar>
  );
});

type SidebarCollapseProps = {} & ComponentProps<typeof FlowbiteSidebar.Collapse>;

const SidebarCollapse = forwardRef((
  {
    active = false,
    as,
    children,
    href,
    icon,
    label,
    labelColor,
    ...otherProps
  }: SidebarCollapseProps,
  ref: LegacyRef<HTMLDivElement & HTMLButtonElement>,
) => {
  return (
    <FlowbiteSidebar.Collapse
      active={active}
      as={as}
      href={href}
      icon={icon}
      label={label}
      labelColor={labelColor}
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteSidebar.Collapse>
  );
});

type SidebarCTAProps = {} & ComponentProps<typeof FlowbiteSidebar.CTA>;

const SidebarCTA = forwardRef((
  {
    children,
    color,
    ...otherProps
  }: SidebarCTAProps,
  ref: LegacyRef<HTMLDivElement>,
) => {
  return (
    <FlowbiteSidebar.CTA
      color={color}
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteSidebar.CTA>
  );
});

type SidebarItemsProps = {} & ComponentProps<typeof FlowbiteSidebar.Items>;

const SidebarItems = forwardRef((
  {
    children,
    ...otherProps
  }: SidebarItemsProps,
  ref: LegacyRef<HTMLDivElement>,
) => {
  return (
    <FlowbiteSidebar.Items
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteSidebar.Items>
  );
});

type SidebarItemGroupProps = {} & ComponentProps<typeof FlowbiteSidebar.ItemGroup>;

const SidebarItemGroup = forwardRef((
  {
    children,
    ...otherProps
  }: SidebarItemGroupProps,
  ref: LegacyRef<HTMLUListElement>,
) => {
  return (
    <FlowbiteSidebar.ItemGroup
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteSidebar.ItemGroup>
  );
});

type SidebarItemProps = {} & ComponentProps<typeof FlowbiteSidebar.Item>;

const SidebarItem = forwardRef((
  {
    active = false,
    as,
    children,
    href,
    icon,
    label,
    labelColor,
    ...otherProps
  }: SidebarItemProps,
  ref: LegacyRef<HTMLDivElement>,
) => {
  return (
    <FlowbiteSidebar.Item
      active={active}
      as={as}
      href={href}
      icon={icon}
      label={label}
      labelColor={labelColor}
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteSidebar.Item>
  );
});

type SidebarLogoProps = {} & ComponentProps<typeof FlowbiteSidebar.Logo>;

const SidebarLogo = forwardRef((
  {
    children,
    className,
    href,
    img,
    imgAlt,
    ...otherProps
  }: SidebarLogoProps,
  ref: LegacyRef<HTMLAnchorElement>,
) => {
  return (
    <FlowbiteSidebar.Logo
      className={className}
      href={href}
      img={img}
      imgAlt={imgAlt}
      ref={ref}
      {...otherProps}
    >
      {children}
    </FlowbiteSidebar.Logo>
  );
});

export default Object.assign(Sidebar, {
  Collapse: SidebarCollapse,
  CTA: SidebarCTA,
  Item: SidebarItem,
  ItemGroup: SidebarItemGroup,
  Items: SidebarItems,
  Logo: SidebarLogo,
});

結果

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

はい、できました。