diff --git a/src/parseProperty.ts b/src/parseProperty.ts index 07a0425..431e72f 100644 --- a/src/parseProperty.ts +++ b/src/parseProperty.ts @@ -11,13 +11,14 @@ export const parseProperty = (state: ParserState, symbol: ts.Symbol) => { const documentationSuffix = documentation ? `\n """\n ${documentation.replaceAll("\n", "\n ")}\n """` : ""; - const definition = parseInlineType( - state, - state.typechecker.getTypeOfSymbol(symbol), - ); - - if (symbol.flags & ts.SymbolFlags.Optional) { - state.imports.add("NotRequired"); + + if (symbol.flags & ts.SymbolFlags.Optional) { + state.imports.add("NotRequired"); + const definition = parseInlineType( + state, + // since the entry is already options, the inner type can be non-nullable + state.typechecker.getNonNullableType(state.typechecker.getTypeOfSymbol(symbol)), + ); if (state.config.nullableOptionals) { state.imports.add("Optional"); return `${name}: NotRequired[Optional[${definition}]]${documentationSuffix}`; @@ -25,6 +26,11 @@ export const parseProperty = (state: ParserState, symbol: ts.Symbol) => { return `${name}: NotRequired[${definition}]${documentationSuffix}`; } } else { + const definition = parseInlineType( + state, + // since the entry is already options, the inner type can be non-nullable + state.typechecker.getTypeOfSymbol(symbol), + ); return `${name}: ${definition}${documentationSuffix}`; } }; diff --git a/src/testing/dicts.test.ts b/src/testing/dicts.test.ts index 7438a1a..4f810b9 100644 --- a/src/testing/dicts.test.ts +++ b/src/testing/dicts.test.ts @@ -64,7 +64,16 @@ class A(TypedDict): expect(result).toContain(`class A(TypedDict):\n foo: NotRequired[str]`); }); - it.only("transpiles optional values with non-null optionals as NotRequired[T]", async () => { + it("transpiles optional values as NotRequired[Optional[T]] in strict mode", async () => { + const result = await transpileString( + `export type A = { foo?: string }`, + {}, + { strict: true }, + ); + expect(result).toContain(`class A(TypedDict):\n foo: NotRequired[str]`); + }); + + it("transpiles optional values with non-null optionals as NotRequired[T]", async () => { const result = await transpileString(`export type A = { foo?: string }`, { nullableOptionals: true, });