🦎

React + TS で動的にタグを変える方法

2021/07/27に公開4

styled-components の as みたいなものどうやってやるんだろうと思い調べてみたので共有です。
結論から書くと次のようにすればいけました。

type Props = {
  as?: React.ElementType;
  text: string;
};

const ReactMozidume: React.VFC<Props> = ({ as: CustomTag = "p", text }) => {
  return (
    <CustomTag>
      {text}
    </CustomTag>
  );
};

as keyof JSX.IntrinsicElements のキャストがないと valid な HTML タグかを TS が分からないので

Type '{ children: string; }' has no properties in common with type 'IntrinsicAttributes'.ts(2559)

というエラーを吐いてしまいます。

Discussion

Hiroki SakanoHiroki Sakano

asの型の部分、stringの代わりにReact.ElementTypeとすると、ある程度簡単に限定できると思いますが、いかがでしょうか?

type Props = {
-  as?: string;
+  as?: React.ElementType;
  text: string;
};
seyaseya

そんな便利型が!ありがとうございます!

sunnyonesunnyone

ElementTypeはIntrinsicElementsを抱えているのでキャストは不要なのではないでしょうか。こんなのでよさそうです:

const ReactMozidume: React.VFC<Props> = ({ as: CustomTag = "p", text }) => 
    <CustomTag>{text}</CustomTag>;
seyaseya

おお、本当だキャストなくしてもコンパイル通りましたね。
ご指摘ありがとうございます!!