When working with TypeScript in React, you often encounter various ways to type HTML elements. Two common types developers use for images are JSX.IntrinsicElements['img']
and HTMLAttributes<HTMLImageElement>
. Though they might seem similar, they serve different purposes and provide distinct benefits depending on your use case. In this blog post, we'll explore the differences between these two approaches, and when you should use one over the other. Keep in mind that I'm using image element as an example here. It's the representation of all available html elements.
What is JSX.IntrinsicElements['img']
? #
- Origin: This comes from React's intrinsic elements, which represent HTML tags like
img
,div
,button
, etc., and their corresponding attributes. - Usage: It represents the props that are allowed for the
img
element when used in JSX (React). This includes all the standard HTML attributes for an image tag, as well as any React-specific attributes likekey
orref
. - Context: It’s used in React when defining props for elements like
img
directly in JSX. It includes both standard HTML and React-specific attributes.
What is HTMLAttributes<HTMLImageElement>
? #
- Origin: This is part of the standard DOM type definitions in TypeScript for HTML attributes, specifically tied to the
HTMLImageElement
interface. - Usage: It represents the standard HTML attributes for an
img
element but without any React-specific props likekey
orref
. It focuses on native DOM attributes and doesn’t include React-specific features. - Context: This type is used when interacting with the DOM directly, such as manipulating elements outside of React or when you’re dealing purely with HTML attributes in TypeScript.
When Should I Use Each? #
When to Use JSX.IntrinsicElements['img']
#
- You’re working in React and want TypeScript to recognize standard image attributes along with React-specific props like
ref
orkey
. - You’re not extending or customizing the behavior of the
img
element beyond what’s typical.
When to Use HTMLAttributes<HTMLImageElement>
#
- You’re building a custom component or utility that interacts directly with the DOM or expects only standard HTML attributes.
- You want to control only the native HTML attributes without React-specific props like
ref
. - You need more control over the types of HTML attributes that can be passed to your component.
Let’s See Some Code! #
Example Using JSX.IntrinsicElements['img']
#
Here’s how you’d use JSX.IntrinsicElements['img']
in a React component:
Loading...
And now, here’s how it looks with HTMLAttributes<HTMLImageElement>
:
Loading...
Why Does ComponentWithHTMLAttributes Accept key? #
HTMLAttributes
doesn’t includekey
by default: TheHTMLAttributes<HTMLImageElement>
type only covers standard HTML attributes (likeclassName
,src
, etc.), but not React-specific attributes likekey
.- React automatically allows
key
: Even thoughHTMLAttributes
doesn't includekey
, TypeScript doesn’t complain when you passkey
toComponenWithHTMLAttributes
because React handles thekey
prop separately. It doesn't passkey
down to the component itself, which is why you can passkey
, and there’s no TypeScript error. - Both serve slightly different purposes, with the former being tailored for React usage and the latter for more generic HTML usage.
- In both cases (
ComponenWithHTMLAttributes
andComponenWithJSXIntrinsicElements
), React is stripping thekey
before passing props to the underlyingimg
tag. - TypeScript knows that
key
is a special prop in React, so it allows you to pass it, even though it’s not part ofHTMLAttributes
. That's becausekey
is handled by React internally and is not passed to the component or to the DOM.
Key Differences: #
- React-Specific Attributes:
JSX.IntrinsicElements['img']
includes both React-specific attributes (key
,ref
) as well as standard HTML attributes, whileHTMLAttributes<HTMLImageElement>
does not include React-specific attributes, focusing only on HTML attributes. - Scope:
JSX.IntrinsicElements['img']
is scoped to React JSX elements and reflects how theimg
element behaves in a React environment.HTMLAttributes<HTMLImageElement>
is more generic and tied to how theimg
element behaves in the DOM, without the React-specific extras.
Summary #
- Use
JSX.IntrinsicElements['img']
when you're working with JSX and want both HTML and React props. - Use
HTMLAttributes<HTMLImageElement>
when you're dealing strictly with HTML attributes or manipulating DOM elements outside of React.