Skip to content

Commit 6b58d29

Browse files
authored
Merge pull request #361 from shilman/341-fix-remove-optional-undefined
Fix shouldRemoveUndefinedFromOptional in TypeScript strict mode
2 parents 33a1ab6 + 87fe8f1 commit 6b58d29

File tree

5 files changed

+127
-3
lines changed

5 files changed

+127
-3
lines changed

.prettierrc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"trailingComma": "none",
3+
"singleQuote": true
4+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import * as React from 'react';
2+
3+
enum sampleEnum {
4+
ONE = 'one',
5+
TWO = 'two',
6+
THREE = 'three'
7+
}
8+
9+
interface RemoveOptionalValuesFromEnumProps {
10+
/** sampleString description */
11+
sampleString?: string;
12+
/** sampleBoolean description */
13+
sampleBoolean?: boolean;
14+
/** sampleEnum description */
15+
sampleEnum?: sampleEnum;
16+
}
17+
18+
/** RemoveOptionalValuesFromEnum description */
19+
export const Stateless: React.StatelessComponent<RemoveOptionalValuesFromEnumProps> = ({
20+
sampleString = 'hello',
21+
sampleBoolean = true,
22+
sampleEnum = 'three'
23+
}) => <div>test</div>;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import * as React from 'react';
2+
3+
interface RemoveOptionalValuesFromUnionProps {
4+
/** sampleStringUnion description */
5+
sampleStringUnion?: 'string1' | 'string2';
6+
/** sampleNumberUnion description */
7+
sampleNumberUnion?: 1 | 2 | 3;
8+
/** sampleMixedUnion description */
9+
sampleMixedUnion?: 1 | 2 | 'string1' | 'string2';
10+
}
11+
12+
export const Stateless: React.StatelessComponent<RemoveOptionalValuesFromUnionProps> = ({
13+
sampleStringUnion = 'string1',
14+
sampleNumberUnion = 1,
15+
sampleMixedUnion = 1
16+
}) => <div>test</div>;

src/__tests__/parser.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1482,6 +1482,78 @@ describe('parser', () => {
14821482
});
14831483
});
14841484

1485+
describe('typescript strict mode', () => {
1486+
// typescript strict mode adds an extra `undefined` to enums
1487+
// may have other funky behavior
1488+
describe('remove undefined from optional', () => {
1489+
const options = {
1490+
shouldExtractLiteralValuesFromEnum: true,
1491+
shouldRemoveUndefinedFromOptional: true,
1492+
savePropValueAsString: true
1493+
};
1494+
const parser = withCustomConfig(
1495+
// tsconfig with strict: true
1496+
path.join(__dirname, '../../src/__tests__/data/tsconfig.json'),
1497+
options
1498+
);
1499+
it('removes undefined from enums', () => {
1500+
const result = parser.parse(
1501+
fixturePath('RemoveOptionalValuesFromEnum')
1502+
);
1503+
const expected = {
1504+
RemoveOptionalValuesFromEnum: {
1505+
sampleBoolean: { type: 'boolean', required: false },
1506+
sampleEnum: {
1507+
raw: 'sampleEnum',
1508+
required: false,
1509+
type: 'enum',
1510+
value: [
1511+
{ value: '"one"' },
1512+
{ value: '"two"' },
1513+
{ value: '"three"' }
1514+
]
1515+
},
1516+
sampleString: { type: 'string', required: false }
1517+
}
1518+
};
1519+
checkComponent(result, expected, false);
1520+
});
1521+
it('removes undefined from unions', () => {
1522+
const result = parser.parse(
1523+
fixturePath('RemoveOptionalValuesFromUnion')
1524+
);
1525+
const expected = {
1526+
RemoveOptionalValuesFromUnion: {
1527+
sampleStringUnion: {
1528+
required: false,
1529+
raw: '"string1" | "string2"',
1530+
type: 'enum',
1531+
value: [{ value: '"string1"' }, { value: '"string2"' }]
1532+
},
1533+
sampleNumberUnion: {
1534+
required: false,
1535+
raw: '1 | 2 | 3',
1536+
type: 'enum',
1537+
value: [{ value: '1' }, { value: '2' }, { value: '3' }]
1538+
},
1539+
sampleMixedUnion: {
1540+
required: false,
1541+
raw: '"string1" | "string2" | 1 | 2',
1542+
type: 'enum',
1543+
value: [
1544+
{ value: '"string1"' },
1545+
{ value: '"string2"' },
1546+
{ value: '1' },
1547+
{ value: '2' }
1548+
]
1549+
}
1550+
}
1551+
};
1552+
check('RemoveOptionalValuesFromUnion', expected, false, null, options);
1553+
});
1554+
});
1555+
});
1556+
14851557
describe('parseWithProgramProvider', () => {
14861558
it('should accept existing ts.Program instance', () => {
14871559
let programProviderInvoked = false;

src/parser.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,9 @@ export class Parser {
576576
}
577577

578578
let propTypeString = this.checker.typeToString(propType);
579+
if (this.shouldRemoveUndefinedFromOptional && !isRequired) {
580+
propTypeString = propTypeString.replace(' | undefined', '');
581+
}
579582

580583
if (propType.isUnion()) {
581584
if (
@@ -590,12 +593,18 @@ export class Parser {
590593
ts.TypeFlags.Undefined)
591594
))
592595
) {
596+
let value = propType.types.map(type => ({
597+
value: this.getValuesFromUnionType(type)
598+
}));
599+
600+
if (this.shouldRemoveUndefinedFromOptional && !isRequired) {
601+
value = value.filter(option => option.value != 'undefined');
602+
}
603+
593604
return {
594605
name: 'enum',
595606
raw: propTypeString,
596-
value: propType.types.map(type => ({
597-
value: this.getValuesFromUnionType(type)
598-
}))
607+
value
599608
};
600609
}
601610
}

0 commit comments

Comments
 (0)