feat: set a better type for the default image loader (#41639)

## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)


Co-authored-by: Steven <229881+styfle@users.noreply.github.com>
This commit is contained in:
ahhshm 2022-10-25 03:29:07 +03:30 committed by GitHub
parent 17a4f6a69f
commit 8678865907
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 41 additions and 11 deletions

View file

@ -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<ImageConfig>
}
type PlaceholderValue = 'blur' | 'empty'
type OnLoad = React.ReactEventHandler<HTMLImageElement> | undefined

View file

@ -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<ImageConfig>
}
export type RemotePattern = {
/**
* Must be `http` or `https`.

View file

@ -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 = []

View file

@ -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<ImageProps, 'loader'>) {
return <Image loader={loader} {...props} />
}

View file

@ -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}
/>
<ImageWithLoader
id="image-with-loader"
alt="image-with-loader"
src="test.jpg"
width={300}
height={300}
/>
<p id="stubtext">This is valid usage of the Image component</p>
</div>
)