Skip to content

Commit b060ff9

Browse files
authored
avoid double optionals in strict mode (#20)
1 parent 76cf1f5 commit b060ff9

File tree

2 files changed

+23
-8
lines changed

2 files changed

+23
-8
lines changed

src/parseProperty.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,26 @@ export const parseProperty = (state: ParserState, symbol: ts.Symbol) => {
1111
const documentationSuffix = documentation
1212
? `\n """\n ${documentation.replaceAll("\n", "\n ")}\n """`
1313
: "";
14-
const definition = parseInlineType(
15-
state,
16-
state.typechecker.getTypeOfSymbol(symbol),
17-
);
18-
19-
if (symbol.flags & ts.SymbolFlags.Optional) {
20-
state.imports.add("NotRequired");
14+
15+
if (symbol.flags & ts.SymbolFlags.Optional) {
16+
state.imports.add("NotRequired");
17+
const definition = parseInlineType(
18+
state,
19+
// since the entry is already options, the inner type can be non-nullable
20+
state.typechecker.getNonNullableType(state.typechecker.getTypeOfSymbol(symbol)),
21+
);
2122
if (state.config.nullableOptionals) {
2223
state.imports.add("Optional");
2324
return `${name}: NotRequired[Optional[${definition}]]${documentationSuffix}`;
2425
} else {
2526
return `${name}: NotRequired[${definition}]${documentationSuffix}`;
2627
}
2728
} else {
29+
const definition = parseInlineType(
30+
state,
31+
// since the entry is already options, the inner type can be non-nullable
32+
state.typechecker.getTypeOfSymbol(symbol),
33+
);
2834
return `${name}: ${definition}${documentationSuffix}`;
2935
}
3036
};

src/testing/dicts.test.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,16 @@ class A(TypedDict):
6464
expect(result).toContain(`class A(TypedDict):\n foo: NotRequired[str]`);
6565
});
6666

67-
it.only("transpiles optional values with non-null optionals as NotRequired[T]", async () => {
67+
it("transpiles optional values as NotRequired[Optional[T]] in strict mode", async () => {
68+
const result = await transpileString(
69+
`export type A = { foo?: string }`,
70+
{},
71+
{ strict: true },
72+
);
73+
expect(result).toContain(`class A(TypedDict):\n foo: NotRequired[str]`);
74+
});
75+
76+
it("transpiles optional values with non-null optionals as NotRequired[T]", async () => {
6877
const result = await transpileString(`export type A = { foo?: string }`, {
6978
nullableOptionals: true,
7079
});

0 commit comments

Comments
 (0)