Skip to content

Commit 51e56b6

Browse files
ggascoignedanez
andauthored
fix: Add support for TSAsExpressions when trying to stringify expressions (#634)
Using a combination of forwardRefs and generics leads to wanting to use type assertions to retain the generic nature of the wrapped class. This plays rather poorly with propTypes. After a lot of mucking around I decided to simply assert the desired type when setting propTypes and defaults. This leads to code like this: ```tsx (MenuItem as ComponentObjectOf<typeof MenuItem>).propTypes - {...} ``` This change extends expressionTo.toArray to deal with the typescript expression. Co-authored-by: Daniel Tschinder <[email protected]>
1 parent 86f01bd commit 51e56b6

File tree

4 files changed

+95
-0
lines changed

4 files changed

+95
-0
lines changed

src/__tests__/__snapshots__/main-test.ts.snap

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,6 +1835,44 @@ Object {
18351835
}
18361836
`;
18371837
1838+
exports[`main fixtures processes component "component_43.tsx" without errors 1`] = `
1839+
Object {
1840+
"description": "",
1841+
"displayName": "MenuItem",
1842+
"methods": Array [],
1843+
"props": Object {
1844+
"children": Object {
1845+
"description": "Menu item contents.",
1846+
"required": false,
1847+
"type": Object {
1848+
"name": "node",
1849+
},
1850+
},
1851+
"classes": Object {
1852+
"description": "Override or extend the styles applied to the component. See CSS API below for more details.",
1853+
"required": false,
1854+
"type": Object {
1855+
"name": "object",
1856+
},
1857+
},
1858+
"component": Object {
1859+
"defaultValue": Object {
1860+
"computed": false,
1861+
"value": "'li'",
1862+
},
1863+
"required": false,
1864+
},
1865+
"disableGutters": Object {
1866+
"defaultValue": Object {
1867+
"computed": false,
1868+
"value": "false",
1869+
},
1870+
"required": false,
1871+
},
1872+
},
1873+
}
1874+
`;
1875+
18381876
exports[`main fixtures processes component "flow-export-type.js" without errors 1`] = `
18391877
Object {
18401878
"description": "This is a Flow class component",
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import MatMenuItem, {
4+
MenuItemProps as MatMenuItemProps,
5+
} from '@mui/material/MenuItem';
6+
7+
export type ComponentObjectOf<
8+
T extends React.ElementType,
9+
P = React.ComponentProps<T>
10+
> = React.FunctionComponent<P>;
11+
12+
export type MenuItemProps<
13+
D extends React.ElementType,
14+
P = {}
15+
> = MatMenuItemProps<D, P>;
16+
17+
const MenuItem = React.forwardRef<MenuItemProps<'li'>>(
18+
<C extends React.ElementType>(
19+
props: MenuItemProps<C, { component?: C }>,
20+
ref: React.Ref<any>
21+
) => {
22+
return <MatMenuItem {...props} ref={ref} />;
23+
}
24+
) as unknown as <C extends React.ElementType = 'li'>(
25+
props: MenuItemProps<C, { component?: C }>
26+
) => React.ReactElement;
27+
28+
(MenuItem as ComponentObjectOf<typeof MenuItem>).propTypes = {
29+
/** Menu item contents. */
30+
children: PropTypes.node,
31+
/** Override or extend the styles applied to the component. See CSS API below for more details. */
32+
classes: PropTypes.object,
33+
};
34+
35+
(MenuItem as ComponentObjectOf<typeof MenuItem>).defaultProps = {
36+
component: 'li',
37+
disableGutters: false,
38+
};
39+
40+
export default MenuItem;

src/utils/__tests__/expressionTo-test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,17 @@ describe('expressionTo', () => {
3838
expressionToArray(expression('foo[{ a(){} }].baz'), noopImporter),
3939
).toEqual(['foo', '{a: <function>}', 'baz']);
4040
});
41+
42+
it('with TSAsExpression', () => {
43+
expect(
44+
expressionToArray(
45+
expression('(baz as X).prop', {
46+
filename: 'file.ts',
47+
parserOptions: { plugins: ['typescript'] },
48+
}),
49+
noopImporter,
50+
),
51+
).toEqual(['baz', 'prop']);
52+
});
4153
});
4254
});

src/utils/expressionTo.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ function toArray(path: NodePath, importer: Importer): string[] {
3636
} else if (t.Identifier.check(node)) {
3737
result.push(node.name);
3838
continue;
39+
} else if (t.TSAsExpression.check(node)) {
40+
if (t.Identifier.check(node.expression)) {
41+
result.push(node.expression.name);
42+
}
43+
continue;
3944
} else if (t.Literal.check(node)) {
4045
// @ts-ignore
4146
result.push(node.raw);

0 commit comments

Comments
 (0)