LoginSignup
6
2

More than 3 years have passed since last update.

typescript 3.7以上で styled-componentsのpropsの型を取り出す

Last updated at Posted at 2020-04-23

typescript 3.7 以上を使用している場合 styled-components で書かれたコンポーネントを ComponentProps を使用して型を取り出そうとしてもうまく取り出せません
これは型定義でコンポーネント呼び出しがオーバーロードされており,2つ目の定義 がComponentProps に渡る為です.(なぜこれがComponentPropsに渡るとうまく型がとりだせないかは長くなるので割愛します

これを解決するために props の型を取り出す型を用意します

import * as React from 'react';
import { StyledComponent, StyledComponentProps } from 'styled-components';

export type ExtractStyledComponentProps<SC> = SC extends StyledComponent<
  infer C,
  infer T,
  infer O,
  infer A
>
  ? StyledComponentProps<C, T, O, A> & {
      as?: keyof JSX.IntrinsicElements | React.ComponentType<any>;
      forwardedAs?: keyof JSX.IntrinsicElements | React.ComponentType<any>;
    }
  : never;
使い方
const Component: React.FC<{ hoge: string, fuga?: number }> = (props) => <div />;
const StyledComponent = styled(Component)`
  background-color: red;
`;

// ------------------------------
// 先ほど作った型を使って propsの型を取り出してみる
type Props = ExtractStyledComponentProps<typeof StyledComponent>;

// Props が意図した型かテスト(vscode等で各変数の型を見てみて下さい)
const test = (props: Props) => {
  const hoge = props.hoge; // => string
  const fuga = props.fuga; // => number | undefined
  const theme = props.theme; // => {}
  const as = props.as;   // => JSX.IntrinsicElements | React.ComponentType<any>
  const forwardedAs = props.forwardedAs; // => JSX.IntrinsicElements | React.ComponentType<any>
};

ExtractStyledComponentProps によって型を取り出すことができるようになりました :tada:

さらに発展させて React コンポーネントなのか styled-components で書かれたコンポーネントなのかを意識せずに型を取り出せるようにしたいと思います

import * as React from 'react';
import { StyledComponent, StyledComponentProps } from 'styled-components';

// 先ほど作った型
export type ExtractStyledComponentProps<SC> = SC extends StyledComponent<....

export type ComponentPropsWithStyledComponents<C> = C extends StyledComponent<any, any, any, any>
  ? ExtractStyledComponentProps<C>
  // StyledComponent の型で無い場合は ComponentProps を使って取り出す
  : React.ComponentProps<C>;
使い方2
const Component: React.FC<{ hoge: string, fuga?: number }> = (props) => <div />;
const StyledComponent = styled(Component)`
  background-color: red;
`;

// ------------------------------
// 先ほど作った型を使って propsの型を取り出す
type Props1 = ComponentPropsWithStyledComponents<typeof StyledComponent>;

// 意図した型かテスト(vscode等で各変数の型を見てみて下さい)
const test1 = (props: Props1) => {
  const hoge = props.hoge; // => string
  const fuga = props.fuga; // => number | undefined
  const theme = props.theme; // => {}
  const as = props.as;   // => JSX.IntrinsicElements | React.ComponentType<any>
  const forwardedAs = props.forwardedAs; // => JSX.IntrinsicElements | React.ComponentType<any>
};

// React.FC 型も試してみる
type Props2 = ComponentPropsWithStyledComponents<typeof Component>;

const test2 = (props: Props2) => {
  const hoge = props.hoge; // => string
  const fuga = props.fuga; // => number | undefined
  const children = props.children; // => React.ReactNode
};

これで無事両方の型を取り出すことができるようになりました

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2