Types of property 'src' are incompatible in nextjs/image
Asked Answered
R

4

17

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?

Reverberation answered 27/6, 2021 at 5:13 Comment(6)
are you loading the image from local path or any remote cdn?Froward
if you are loading image locally then you should use import image from "img/path"; & <Image src={image} alt="something"Froward
no bro I m using API call for that...if the image was coming from locally that was so much easy.Reverberation
adding a width and height props will solved it. you may also want to add layout.Diestock
if it is from remote api call then why are you using /images/? in your remote api response it should be a cdn link which will have a url. so it sould be <Image src={url} /> something like this.Froward
Having the same issue here.Birthright
M
15

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.

Magdala answered 27/6, 2021 at 7:5 Comment(0)
E
8

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 TestComponent(props: Record<string, string>) {
  const { imageResource } = props;
  return (
        <Image
          loader={myLoader}
          src={`/${imageResource}`}
          width="20%"
          height="20%"
        />
  );
}
Echikson answered 15/9, 2022 at 12:16 Comment(0)
B
-1

I omitted placeholder, blurDataURL and layout. I also made explicity src as string. More info on this issue: https://github.com/vercel/next.js/issues/26735

Birthright answered 13/7, 2021 at 16:59 Comment(0)
M
-2

Just cast string as a any

<Image src={'string' as any} alt='Pic' />
Marinara answered 2/8, 2021 at 6:8 Comment(2)
I think the assumption is when a question around TypeScript is posed, OP is aware that casting as any is an option, but is looking for a strongly typed solution.Holiday
Well, it's true that casting solves the problem very easily <Image src={imgURL as string} alt={imgName as string} />Pertussis

© 2022 - 2024 — McMap. All rights reserved.