0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

フロントエンド開発で役に立つTipsAdvent Calendar 2023

Day 10

ComponentPropsWithoutRefとJSX.IntrinsicElementsの違いってなに?

Last updated at Posted at 2023-12-09

型の定義でComponentPropsWithoutRefJSX.IntrinsicElementsというものがあることを知りました。
違いがわからなかったので調べてみました。

ComponentPropsWithoutRefとは?

指定したHTML要素のPropsの型を取得します。
この型は、HTML要素の全てのネイティブ属性をPropsとして取得します。

JSX.IntrinsicElementsとは?

Reactの型定義の一部で、HTML要素のPropsの型を定義するために使用します。

2つの型の違いは?

ComponentPropsWithoutRefは、型を取得するのに対して、JSX.IntrinsicElementsは、型を定義します。

は?って感じですよね…私も同じ感情を持ちました…
具体的な例で確認してみたいと思います。

例えば下記のような書き方だとエラーになります。

export interface Props extends JSX.IntrinsicElements['li'] {
  specialProp?: string;
}

下記の記述方法だとエラーになりません。

export interface Props extends ComponentPropsWithoutRef<'li'> {
  specialProp?: string;
}

エラーの内容は下記のとおりです。

インターフェイスが拡張するのは、オプションの型引数が指定された識別子/完全修飾名のみです。

TypeScriptの制限で、typeは直接的に拡張できるのに対してinterfaceはできないとのことです。

エラーを出さずにJSX.IntrinsicElements['li']を利用する方法

JSX.IntrinsicElements['li']を使いつつ、エラーを出さないで拡張した型を作る方法を紹介します。

解決策①
type listItemProps = JSX.IntrinsicElements['li'];
export interface Props extends listItemProps {
  specialProp?: string;
}

一度type(Type Alias)を利用して、JSX.IntrinsicElements['li']の方に名前をつけます。
その上でextendsするとエラーは発生しません。

interfaceを使わずtypeを利用するとJSXの記述でも拡張ができる

解決策②
type Props = JSX.IntrinsicElements["li"] & {
  hogehoge: string
}

interfaceではなく、type(Type Alias)を利用します。
&を利用して型を拡張することで解決策①よりもシンプルに書けます。

【ComponentPropsとJSX.IntrinsicElementsの違い】まとめ

まだ紐解けてない部分はありますが、typeを利用するかinterfaceを利用するかで選択が変わりそうだと思います。

一般的にはtypeは柔軟でinterfaceはオブジェクトの型を定義する時に用いられるようです。

適切な型定義の方法を選べるようになるために引き続き精進します。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?