SolvedDefinitelyTyped [@types/styled-components] How do you use attrs?
✔️Accepted Answer
The answer everybody was looking for:
import styled from 'styled-components'
const Container = styled.div.attrs<
{ size: number }, // What is consumed by .attrs()
{ width: number, height: number } // What comes out of .attrs()
>((props) => {
return {
width: props.size,
height: props.size,
}
})<{ size: number }> // The outer type
`
width: ${props => props.width}px;
height: ${props => props.width}px;
`
const container = <Container size={200} />
Other Answers:
I solved it temporarily.
import styled from 'styled-components';
import React from 'react';
interface AdditionalProps2 {
size22: string;
// size: string; // not works if this line uncommented.
}
const WeirdComponent = styled.input.attrs<AdditionalProps2>({})<AdditionalProps2>`
color: palevioletred;
font-size: 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
export const X = () => <WeirdComponent size22={'massive'} size={324} defaultValue="dsdsd" />;
Seems like size
property is conflicting with React InputHTMLAttributes<T>
interface InputHTMLAttributes<T> extends HTMLAttributes<T> {
...
pattern?: string;
placeholder?: string;
readOnly?: boolean;
required?: boolean;
size?: number; //already defined
src?: string;
step?: number | string;
...
}
And attrs
calculates its attributes using diff between additional props & react element attributes.
export interface ThemedStyledFunction<P, T, O = P> {
(
strings: TemplateStringsArray,
...interpolations: Interpolation<ThemedStyledProps<P, T>>[]
): StyledComponentClass<P, T, O>
<U>(
strings: TemplateStringsArray,
...interpolations: Interpolation<ThemedStyledProps<P & U, T>>[]
): StyledComponentClass<P & U, T, O & U>
attrs<U, A extends Partial<P & U> = {}>(
attrs: Attrs<P & U, A, T>
): ThemedStyledFunction<DiffBetween<A, P & U>, T, DiffBetween<A, O & U>>
}
So below code works.
interface AdditionalProps2 {
size22: string;
// size: string; // not works if this line uncommented.
}
const WeirdComponent = styled.input.attrs<AdditionalProps2>({ })`
color: palevioletred;
font-size: 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
export const X = () => (
<WeirdComponent size22={"massive"} size={324} defaultValue='dsdsd'/>
);
Thanks for the tip. In my case, TS was able to infer the "what comes out of attrs", but the final "outer type" was the trick I needed. So I just did:
const Foo = styled.div.attrs<{ width: number }>(
({width}) => ({ style: ... })
)<{ width: number }>`
...
`;
Hey, @antoinerousseau, does this help? I wish this example had been around when I was first looking!
Using custom props with Styled Components in Typescript.
Custom props are props which are not valid HTML attributes of the element being styled.
Choose prop names which will clearly never conflict with any default attributes of the tag being used. eg. isFixed
is not among the valid DIV attributes.
interface Props {
isFixed?: boolean
}
const Box = styled.div`
position: ${({ isFixed = false }: Props) => (isFixed ? 'fixed' : 'absolute')};
top: 0;
`
export default () => (
<div>
<Box isFixed={true}>I'm a box</Box>
</div>
)
Using custom props and html element attributes with Styled Components in Typescript.
In this case type
is among the valid attributes of the button
element, and isFixed
is not!
I've found it useful to use separate interface
statements for attrs
and props
.
interface Props {
isFixed?: boolean
}
interface Attrs {
type?: string
}
const Button = styled.button.attrs(({ type = 'button' }: Attrs) => ({
type,
}))`
position: ${({ isFixed = false }: Props) => (isFixed ? 'fixed' : 'absolute')};
`
export default () => (
<div>
<Button isFixed={true} type="submit">
I'm a button with type "submit" instead of default type of "button"
</Button>
</div>
)
@Igorbek @probablyup originally posted this in styled-components/styled-components#1959 and was told to post here.
Hi, it's unclear how
attrs
should be used with TypeScript, I'm not sure if there's just a bug in the types. Here's what we've got so far, this is the only way to make the component definition work as expected, but then the component usage fails with the error[ts] Type 'string' is not assignable to type 'never'.
.Environment