I just copy-pasted the components, but I believe their content is irrelevant. The problem is that the codemod doesn't respect passed options.
Faulty codemod
react-prop-types-typescript
doesn't respect the preserver-prop-types
(in both VS Code and CLI).
Code before transformation
import { styled } from '@mui/material/styles'
import PropTypes from 'prop-types'
const Root = styled('button', {
name: 'SegmentedTab',
shouldForwardProp: (property) => property !== 'isSelected',
// @ts-expect-error TS(2339): Property 'isSelected' does not exist on type 'MUIS... Remove this comment to see the full error message
})(({ isSelected, theme }) => ({
'&:hover': {
// @ts-expect-error TS(2339): Property 'neutral' does not exist on type 'Palette... Remove this comment to see the full error message
background: theme.palette.neutral[200],
},
alignItems: 'center',
background: 'transparent',
border: 'none',
borderRadius: 999,
color: theme.palette.text.primary,
cursor: 'pointer',
display: 'flex',
flex: 1,
fontFamily: theme.typography.fontFamily,
fontSize: 'inherit',
fontWeight: 'inherit',
justifyContent: 'center',
padding: 0,
textDecoration: 'none',
...(isSelected && {
'&, &:hover': {
background: 'white',
},
}),
}))
export default function SegmentedTab({
component = 'button',
isSelected,
...other
}: any) {
const Component = Root.withComponent(component)
return <Component isSelected={isSelected} {...other} />
}
SegmentedTab.propTypes = {
/** React component or HTML element name that is used to render tabs. */
component: PropTypes.elementType,
/** Marks the tab as a selected. */
isSelected: PropTypes.bool.isRequired,
}
Expected code after transformation
import { styled } from '@mui/material/styles'
const Root = styled('button', {
name: 'SegmentedTab',
shouldForwardProp: (property) => property !== 'isSelected',
// @ts-expect-error TS(2339): Property 'isSelected' does not exist on type 'MUIS... Remove this comment to see the full error message
})(({ isSelected, theme }) => ({
'&:hover': {
// @ts-expect-error TS(2339): Property 'neutral' does not exist on type 'Palette... Remove this comment to see the full error message
background: theme.palette.neutral[200],
},
alignItems: 'center',
background: 'transparent',
border: 'none',
borderRadius: 999,
color: theme.palette.text.primary,
cursor: 'pointer',
display: 'flex',
flex: 1,
fontFamily: theme.typography.fontFamily,
fontSize: 'inherit',
fontWeight: 'inherit',
justifyContent: 'center',
padding: 0,
textDecoration: 'none',
...(isSelected && {
'&, &:hover': {
background: 'white',
},
}),
}))
interface SegmentedTabProps {
/** React component or HTML element name that is used to render tabs. */
component?: React.ElementType;
/** Marks the tab as a selected. */
isSelected: boolean;
}
export default function SegmentedTab({
component = 'button',
isSelected,
...other
}: SegmentedTabProps) {
const Component = Root.withComponent(component)
return <Component isSelected={isSelected} {...other} />
}
SegmentedTab.propTypes = {
/** React component or HTML element name that is used to render tabs. */
component: PropTypes.elementType,
/** Marks the tab as a selected. */
isSelected: PropTypes.bool.isRequired,
}
Actual code after transformation
import { styled } from '@mui/material/styles'
const Root = styled('button', {
name: 'SegmentedTab',
shouldForwardProp: (property) => property !== 'isSelected',
// @ts-expect-error TS(2339): Property 'isSelected' does not exist on type 'MUIS... Remove this comment to see the full error message
})(({ isSelected, theme }) => ({
'&:hover': {
// @ts-expect-error TS(2339): Property 'neutral' does not exist on type 'Palette... Remove this comment to see the full error message
background: theme.palette.neutral[200],
},
alignItems: 'center',
background: 'transparent',
border: 'none',
borderRadius: 999,
color: theme.palette.text.primary,
cursor: 'pointer',
display: 'flex',
flex: 1,
fontFamily: theme.typography.fontFamily,
fontSize: 'inherit',
fontWeight: 'inherit',
justifyContent: 'center',
padding: 0,
textDecoration: 'none',
...(isSelected && {
'&, &:hover': {
background: 'white',
},
}),
}))
interface SegmentedTabProps {
/** React component or HTML element name that is used to render tabs. */
component?: React.ElementType;
/** Marks the tab as a selected. */
isSelected: boolean;
}
export default function SegmentedTab({
component = 'button',
isSelected,
...other
}: SegmentedTabProps) {
const Component = Root.withComponent(component)
return <Component isSelected={isSelected} {...other} />
}
Estimated severity
It's quite a sever issue to us. We have hundreds of components we want to add types to, preserving prop types. Doing it manually is not an option.
Looks like a trivial issue to fix. The codemod doesn't pick up the preserver-prop-types
option, neither from VS Code nor from the console. Feels like a typo to me, but I couldn't find a way to debug it myself.
Environment:
- Codemod CLI version: v0.10.14
- OS: macOS 14.4.1
- Node.js version: v18.19.1