-
Notifications
You must be signed in to change notification settings - Fork 30.6k
[styled-system/components - react] Overwriting HTMLAttributes w/ own type def #29629
Description
@types/react: "^16.4.9"
@types/styled-system: "^3.0.1",
@types/styled-components: "^4.0.0"
- I tried using the
@types/packagepackage and had problems. - I tried using the latest stable version of tsc. https://www.npmjs.com/package/typescript
- I have a question that is inappropriate for StackOverflow. (Please ask any appropriate questions there).
- Mention the authors (see
Definitions by:inindex.d.ts) so they can respond.- Authors styled-system: @maxdeviant, @phobon, @zephraph, @damassi, @alloy, @maoueh, @lavoaster
- Authors styled-components: @Igorbek, @Igmat
- Authors react: @bbenezech, @pzavolinsky, @digiguru, @ericanderson, @morcerf
I'm utilizing typescript, react, styled-components and styled-system to build out a design system. I cannot write my own type definitions that will overwrite types in HTMLAttributes interfaces, specifically interface ImgHTMLAttributes
Specifically, I'd like to pass an array to width on an image, as performed in styled-system, but the width property on ImgHTMLAttributesonly allows for a single string | number.
If the html element doesn't have a property defined on it's base interface, then I'm successfully able to define and use the property as I'd like.
For example, I've created a <Box /> component, which is a div. On it's interface, I can define width to accept whatever I choose, and successfully use width={[ 1, 1/2 ]}.
Here's the code.
This is my base box. Note that I'm importing the WidthProps interface from styled-system
import { width, WidthProps, (...more) } from 'styled-system';
import styled, { css } from '../styled-components';
import { IThemeInterface } from '../theme';
export interface IBox extends SpaceProps, WidthProps (...more) {
/** Emergency Hatch - One-off CSS Rule Object */
css?: any;
/** Set of rules that define rules / styles */
theme?: IThemeInterface;
}
export const baseRules = css`
${width}
(...more)
`;
export const Box = styled.div<IBox>`
${() => baseRules};
`;
Box.displayName = 'Box';
export default Box;Within @types/styled-system, the WidthProps are defined as:
export interface WidthProps {
width?: ResponsiveSpaceValue;
}I can use this box just fine like so
<Box width={[1 / 2, 1]}>
Hello
</Box>and here is my Image
import { borderRadius, BorderRadiusProps } from 'styled-system';
import { baseRules, IBox } from '../Box/Box';
import styled from '../styled-components';
interface IImage extends IBox, BorderRadiusProps {}
export const Image = styled.img<IImage>`
${() => baseRules};
${borderRadius};
max-width: 100%;
height: auto;
`;
Image.displayName = 'Image';
export default Image;When hovering over Image, you get
const Image: StyledComponentClass<ClassAttributes<HTMLImageElement> & ImgHTMLAttributes<HTMLImageElement> & IImage, IThemeInterface, ClassAttributes<HTMLImageElement> & ImgHTMLAttributes<HTMLImageElement> & IImage>When trying to use <Image /> like so
<Image width={[1 / 2, 1 / 3]} alt="Tesla Roadster" src={roadster} />I get the error
Type 'number[]' is not assignable to type 'string | number | (string & (string | number | null)[]) | (number & (string | number | null)[]) | undefined'.
Type 'number[]' is not assignable to type 'number & (string | number | null)[]'.
Type 'number[]' is not assignable to type 'number'.
The expected type comes from property 'width' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<ThemedOuterStyledProps<ClassAttributes<HTMLImageElement> & ImgHTMLAttributes<HTMLImageElement> & IImage, IThemeInterface>, ComponentState, any>> & Readonly<...> & Readonly<...>'
When following the error message, I get linked to interface ImgHTMLAttributes within @types/react which has it has a own width definition:
interface ImgHTMLAttributes<T> extends HTMLAttributes<T> {
alt?: string;
crossOrigin?: "anonymous" | "use-credentials" | "";
height?: number | string;
sizes?: string;
src?: string;
srcSet?: string;
useMap?: string;
width?: number | string;
}I tried adding an additional width type to my interface to overwrite the HTML and it didn't work. The only time there was any affect was if i placed type any on width like so (but this kills typing):
interface IImage extends IBox, BorderRadiusProps {
width?: any;
}I also tried to see if i could edit ImgHTMLAttributes by doing the following:
declare module 'react' {
interface ImgHTMLAttributes<T> {
width?: any;
}
}But I get an error
"message": "Subsequent property declarations must have the same type. Property 'width' must be of type 'string | number | undefined', but here has type 'any'.",
I also came across similar issues #22933 and #14934, but not sure how to make appropriate changes.
How would I be able to get this to work? Is what I want to do possible? Thanks in advance.