diff --git a/packages/next/client/image.tsx b/packages/next/client/image.tsx index bced56ead347599..7788f6a9e10f765 100644 --- a/packages/next/client/image.tsx +++ b/packages/next/client/image.tsx @@ -13,6 +13,8 @@ import { getImageBlurSvg } from '../shared/lib/image-blur-svg' import { ImageConfigComplete, imageConfigDefault, + ImageLoaderProps, + ImageLoaderPropsWithConfig, } from '../shared/lib/image-config' import { ImageConfigContext } from '../shared/lib/image-config-context' import { warnOnce } from '../shared/lib/utils' @@ -33,21 +35,14 @@ if (typeof window === 'undefined') { const VALID_LOADING_VALUES = ['lazy', 'eager', undefined] as const type LoadingValue = typeof VALID_LOADING_VALUES[number] type ImageConfig = ImageConfigComplete & { allSizes: number[] } -export type ImageLoader = (p: ImageLoaderProps) => string -export type ImageLoaderProps = { - src: string - width: number - quality?: number -} +export { ImageLoaderProps } +export type ImageLoader = (p: ImageLoaderProps) => string // Do not export - this is an internal type only // because `next.config.js` is only meant for the // built-in loaders, not for a custom loader() prop. type ImageLoaderWithConfig = (p: ImageLoaderPropsWithConfig) => string -type ImageLoaderPropsWithConfig = ImageLoaderProps & { - config: Readonly -} type PlaceholderValue = 'blur' | 'empty' type OnLoad = React.ReactEventHandler | undefined diff --git a/packages/next/shared/lib/image-config.ts b/packages/next/shared/lib/image-config.ts index d72a4caacaab7d6..e13cdb694371286 100644 --- a/packages/next/shared/lib/image-config.ts +++ b/packages/next/shared/lib/image-config.ts @@ -8,6 +8,16 @@ export const VALID_LOADERS = [ export type LoaderValue = typeof VALID_LOADERS[number] +export type ImageLoaderProps = { + src: string + width: number + quality?: number +} + +export type ImageLoaderPropsWithConfig = ImageLoaderProps & { + config: Readonly +} + export type RemotePattern = { /** * Must be `http` or `https`. diff --git a/packages/next/shared/lib/image-loader.ts b/packages/next/shared/lib/image-loader.ts index ef9d5b6cba90c84..2313f5e2ff23316 100644 --- a/packages/next/shared/lib/image-loader.ts +++ b/packages/next/shared/lib/image-loader.ts @@ -1,5 +1,11 @@ -// TODO: change "any" to actual type -function defaultLoader({ config, src, width, quality }: any): string { +import type { ImageLoaderPropsWithConfig } from './image-config' + +function defaultLoader({ + config, + src, + width, + quality, +}: ImageLoaderPropsWithConfig): string { if (process.env.NODE_ENV !== 'production') { const missingValues = [] diff --git a/test/integration/next-image-new/typescript/components/image-with-loader.tsx b/test/integration/next-image-new/typescript/components/image-with-loader.tsx new file mode 100644 index 000000000000000..b69db19ecb62506 --- /dev/null +++ b/test/integration/next-image-new/typescript/components/image-with-loader.tsx @@ -0,0 +1,11 @@ +import Image from 'next/image' +import type { ImageProps, ImageLoader, ImageLoaderProps } from 'next/image' + +function myLoader({ src, width, quality }: ImageLoaderProps): string { + return `https://example.com/${src}?w=${width}&q=${quality || 75}` +} +const loader: ImageLoader = myLoader + +export function ImageWithLoader(props: Omit) { + return +} diff --git a/test/integration/next-image-new/typescript/pages/valid.tsx b/test/integration/next-image-new/typescript/pages/valid.tsx index 1dcc3b8a94f5ceb..3987bda79cf8ac6 100644 --- a/test/integration/next-image-new/typescript/pages/valid.tsx +++ b/test/integration/next-image-new/typescript/pages/valid.tsx @@ -5,6 +5,7 @@ import svg from '../public/test.svg' import avif from '../public/test.avif' import { ImageCard } from '../components/image-card' import { DynamicSrcImage } from '../components/image-dynamic-src' +import { ImageWithLoader } from '../components/image-with-loader' const Page = () => { return ( @@ -95,6 +96,13 @@ const Page = () => { width={400} height={400} /> +

This is valid usage of the Image component

)