I am using react dropzone to upload multi-image in my simple application. For showing which type of images are drop for that I make a separate component with TypeScript. But Next.js image src is showing error like Type:
'{ src: string; alt: string; }' is not assignable to type 'IntrinsicAttributes & ImageProps'.
Type '{ src: string; alt: string; }' is not assignable to type 'ObjectImageProps'.
Types of property 'src' are incompatible.
Type 'string' is not assignable to type 'StaticImport'.
RenderFiles.ts:
import { IFile } from "../../libs/types";
import { sizeInMb } from "../../libs/sizeInMb";
import { FunctionComponent } from "react";
import Image from "next/image"
const RenderFile: FunctionComponent<{
file: IFile;
}> = ({ file: { formate, sizeInBytes, name } }) => {
return (
<div>
<Image src={`/images/${formate}.png`} alt="image"/>
<span>{name}</span>
<span>{sizeInMb(sizeInBytes)}</span>
</div>
);
};
export default RenderFile;
types.ts:
export interface IFile {
name: string;
sizeInBytes: number;
formate: string | number;
id?: string;
}
What is my mistake in src props?
An alternative is to use <img /> tag instead of Next JS <Image /> tag.
There are two ways you can display images in Next. js, you either use the conventional <img> tag or a specialized <Image/> component that is unique to Next. The differences between these tags are quite much, but they pretty much do the same thing; which is to display images to the browser.
Firstly import the image component in next. js and define the image path in src props in the image component. Now your image shows in the browser. In the image component, src, width, and height props are required by next.
The issue is next/image
's Image
is expecting rather complex type ImageProps
as it's props:
type StringImageProps = {
src: string
} & (
| { width?: never; height?: never; layout: 'fill' }
| {
width: number | string
height: number | string
layout?: Exclude<LayoutValue, 'fill'>
}
) &
(
| {
placeholder?: Exclude<PlaceholderValue, 'blur'>
blurDataURL?: never
}
| { placeholder: 'blur'; blurDataURL: string }
)
type ObjectImageProps = {
src: StaticImport
width?: number | string
height?: number | string
layout?: LayoutValue
placeholder?: PlaceholderValue
blurDataURL?: never
}
export type ImageProps = Omit<
JSX.IntrinsicElements['img'],
'src' | 'srcSet' | 'ref' | 'width' | 'height' | 'loading' | 'style'
> & {
loader?: ImageLoader
quality?: number | string
priority?: boolean
loading?: LoadingValue
unoptimized?: boolean
objectFit?: ImgElementStyle['objectFit']
objectPosition?: ImgElementStyle['objectPosition']
} & (StringImageProps | ObjectImageProps)
Since you're not importing image from local imports the only structure you're left is StringImageProps
. To conform to it you have to provide one of the following props sets:
<Image src={string} layout="fill" />
// or
<Image src={string} width={number} height={number} /> // with optional `layout` prop but not of type 'fill'
both variants may be extended with optional placeholder
(not of type 'blur') or required placeholder: 'blur'
and blurDataURL: string
.
And only after that you may provide native image
's attributes as alt
.
Importing the type for ImageLoaderProps
solved the issue for me.
Example:
import Image from 'next/image';
import type { ImageLoaderProps } from 'next/image';
const myLoader = ({ src, width, quality }: ImageLoaderProps) => {
return `https://example.com/?${src}?w=${width}&q=${quality}`;
};
export default function AppStoreBox(props: Record<string, string>) {
const { imageResource } = props;
return (
<Image
loader={myLoader}
src={`/${imageResource}`}
width="20%"
height="20%"
/>
);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With