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 によって型を取り出すことができるようになりました
さらに発展させて 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
};
これで無事両方の型を取り出すことができるようになりました