diff --git a/packages/next/client/image.tsx b/packages/next/client/image.tsx index 23800bb803348..f9a2622145840 100644 --- a/packages/next/client/image.tsx +++ b/packages/next/client/image.tsx @@ -86,21 +86,16 @@ function isStaticImport(src: string | StaticImport): src is StaticImport { type StringImageProps = { src: string + width?: number | string + height?: number | string + layout?: LayoutValue } & ( - | { width?: never; height?: never; layout: 'fill' } | { - width: number | string - height: number | string - layout?: Exclude + placeholder?: Exclude + blurDataURL?: never } -) & - ( - | { - placeholder?: Exclude - blurDataURL?: never - } - | { placeholder: 'blur'; blurDataURL: string } - ) + | { placeholder: 'blur'; blurDataURL: string } +) type ObjectImageProps = { src: StaticImport @@ -381,6 +376,11 @@ export default function Image({ `Image with src "${src}" has invalid "width" or "height" property. These should be numeric values.` ) } + if (layout === 'fill' && (width || height)) { + console.warn( + `Image with src "${src}" and "layout='fill'" has unused properties assigned. Please remove "width" and "height".` + ) + } if (!VALID_LOADING_VALUES.includes(loading)) { throw new Error( `Image with src "${src}" has invalid "loading" property. Provided "${loading}" should be one of ${VALID_LOADING_VALUES.map( @@ -472,10 +472,24 @@ export default function Image({ } : undefined), } - if ( + if (layout === 'fill') { + // + wrapperStyle = { + display: 'block', + overflow: 'hidden', + + position: 'absolute', + top: 0, + left: 0, + bottom: 0, + right: 0, + + boxSizing: 'border-box', + margin: 0, + } + } else if ( typeof widthInt !== 'undefined' && - typeof heightInt !== 'undefined' && - layout !== 'fill' + typeof heightInt !== 'undefined' ) { // const quotient = heightInt / widthInt @@ -518,25 +532,6 @@ export default function Image({ height: heightInt, } } - } else if ( - typeof widthInt === 'undefined' && - typeof heightInt === 'undefined' && - layout === 'fill' - ) { - // - wrapperStyle = { - display: 'block', - overflow: 'hidden', - - position: 'absolute', - top: 0, - left: 0, - bottom: 0, - right: 0, - - boxSizing: 'border-box', - margin: 0, - } } else { // if (process.env.NODE_ENV !== 'production') { diff --git a/test/integration/image-component/typescript/components/image-card.tsx b/test/integration/image-component/typescript/components/image-card.tsx new file mode 100644 index 0000000000000..b62f4f821d677 --- /dev/null +++ b/test/integration/image-component/typescript/components/image-card.tsx @@ -0,0 +1,14 @@ +import React from 'react' +import Image, { ImageProps } from 'next/image' + +type ImageCardProps = ImageProps & { + id: string + optional?: string +} + +/** + * Example of using the `Image` component in a HOC. + */ +export function ImageCard(props: ImageCardProps) { + return +} diff --git a/test/integration/image-component/typescript/pages/invalid.tsx b/test/integration/image-component/typescript/pages/invalid.tsx index e39b1d7da3087..7d3b03dcb8247 100644 --- a/test/integration/image-component/typescript/pages/invalid.tsx +++ b/test/integration/image-component/typescript/pages/invalid.tsx @@ -5,10 +5,6 @@ const Invalid = () => { return (

Invalid TS

- { return ( @@ -75,6 +76,14 @@ const Page = () => { placeholder="blur" /> + +

This is valid usage of the Image component

) diff --git a/test/integration/image-component/typescript/test/index.test.js b/test/integration/image-component/typescript/test/index.test.js index 1aaa73c678cbb..32a994cd53758 100644 --- a/test/integration/image-component/typescript/test/index.test.js +++ b/test/integration/image-component/typescript/test/index.test.js @@ -73,8 +73,9 @@ describe('TypeScript Image Component', () => { it('should print error when invalid Image usage', async () => { await renderViaHTTP(appPort, '/invalid', {}) + expect(output).toMatch(/Error: Image/) expect(output).toMatch( - /must use "width" and "height" properties or "layout='fill'" property/ + /has "placeholder='blur'" property but is missing the "blurDataURL" property/ ) }) })