'Typescript and defaultProps on a styled component
I have the following styled component:
import styled from "styled-components"
import { rem } from 'polished';
import theme from '../../theme';
type ButtonType = {
intent?: keyof typeof theme.button;
};
const Button = styled.button<ButtonType>`
border: ${({ intent }) => rem(theme.button[intent]["border-width"])} ${({ intent }) => theme.button[intent]["border-style"]} ${({ intent }) => theme.button[intent]["border-color"]};
color: ${({ intent }) => theme.button[intent].color};
`;
Button.defaultProps = {
intent: 'default',
};
export default Button;
where the theme is:
const intent = {
default: '#000000',
error: '#FF0000',
warning: '#FF7900',
};
const theme = {
button: {
default: {
'border-color': intent.default,
'border-style': intent.default,
'border-width': 2,
color: intent.default,
},
error: {
'border-color': intent.error,
'border-style': intent.error,
'border-width': 2,
color: intent.error,
},
warning: {
'border-color': intent.warning,
'border-style': intent.warning,
'border-width': 2,
color: intent.warning,
}
}
};
export default theme;
I'm getting the following Typescript error:
Type 'undefined' cannot be used as an index type.
Not sure why it is assuming that intent is ever undefined if it is defined in the defaultProps - how can I get TypeScript to recognise this?
Solution 1:[1]
Based on your type definition for ButtonType, it is possible for intent to be undefined. Typescript compiler detects that and gives you the said error.
Making intent non-optional should fix the issue:
type ButtonType = {
intent: keyof typeof theme.button;
};
Solution 2:[2]
TypeScript is not going to pick up on anything you define via Button.defaultProps, so it doesn't "know" that it has a default value. Instead you may have to set the default value directly in the component definition:
const Button = styled.button<ButtonType>`
border: ${({ intent = 'default' }) => rem(theme.button[intent]["border-width"])} ${({ intent = 'default' }) => theme.button[intent]["border-style"]} ${({ intent = 'default' }) => theme.button[intent]["border-color"]};
color: ${({ intent = 'default' }) => theme.button[intent].color};
`;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | hawschiat |
| Solution 2 | jered |
