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?
CodePudding user response:
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;
};
CodePudding user response:
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};
`;