Skip to content

fix: type nullable TypeScript model properties as T | null - #2023

Merged
ChiragAgg5k merged 1 commit into
mainfrom
fix/ts-nullable-model-properties
Oct 13, 2026
Merged

ChiragAgg5k merged 1 commit into
mainfrom
fix/ts-nullable-model-properties

Conversation

@ChiragAgg5k

Copy link
Copy Markdown
Member

Closes #2021

What

The TypeScript SDKs (web, node, react-native, deno) typed nullable: true model properties as optional only (passwordPwned?: boolean). The API documents and returns null for these, so under strictNullChecks the real value couldn't be represented. Every other SDK already encodes it (Bool?, bool?, *bool, ?bool, Optional[bool], Option<bool>).

Nullable properties now render as T | null. Optional non-nullable properties stay ?: T.

passwordPwned?: boolean | null;

This applies to response models and request models in all four TS SDKs.

How

  • tsModelProperty takes a nullable flag, so the formatter sees the full type when deciding on line breaks. Generated code has to be Prettier-clean already, and Prettier 3.9.6 lays out an overflowing T | null in one of three ways. I checked each layout against Prettier directly:
    • break after the colon when T | null fits on the next line (plain names, arrays and union arrays)
    • leading pipes for a union array that doesn't fit, expanding the inner union when that overflows too
    • left on one line otherwise (generics, or nothing fits)
  • web/src/models.ts.twig, react-native/src/models.ts.twig and node/src/models/requestModel.ts.twig pass property | schemaNullable. deno/src/models.d.ts.twig appends | null.

Release note

Widening a property's type breaks source compatibility for strict TypeScript consumers whose reads assumed T | undefined. This should ship in the next major of each TS SDK.

Tests

One shared e2e line that every SDK prints:

  • The fixture preset model gains an optional nullable verified boolean. The mock server's GET /mock/tests/general/preset returns it as null.
  • New Base::NULLABLE_MODEL_RESPONSES (preset verified: null) sits next to MODEL_DEFAULT_RESPONSES in every e2e class that uses it (all 33). Each language program prints the decoded value: apple, swift, android, kotlin, dart, flutter, dotnet, unity, go, go-v2, php, python, ruby, rust, node, web (node and chromium), react-native and deno. This also covers decoding of an explicit null in every SDK.
  • JS_MODEL_TO_STRING_RESPONSES now includes "verified":null, so the JS SDKs keep the null through toString().
  • The Deno program reads the value through Models.Preset["verified"] and assigns null to it, so Deno 1.19 (which type-checks on deno run) fails to compile without this fix.

Verification

  • e2e run locally and passing: PHP85, Python313, Go118, Ruby31, Node20, Deno1303, WebNode. CI covers the rest.
  • npm run format:check, lint and analyse pass on web (client), node (server, including npm test) and react-native (client), generated from the live 2.4.x spec. The diff touches 303 node model properties and adds only | null.
  • The overflow layouts were checked by generating node from a scratch spec with long nullable names, arrays and union arrays, then running prettier --check.
  • The Generation suite, composer lint, composer refactor:check and composer lint-twig all pass.

The API returns null for nullable response fields such as passwordPwned, but the web, node, react-native and deno models typed them as optional only, so the value was unrepresentable under strictNullChecks. Every other SDK already encodes nullability.
@ChiragAgg5k ChiragAgg5k self-assigned this Oct 13, 2026
@ChiragAgg5k
ChiragAgg5k merged commit 5470c1c into main Oct 13, 2026
60 checks passed
@ChiragAgg5k
ChiragAgg5k deleted the fix/ts-nullable-model-properties branch October 13, 2026 13:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TypeScript SDKs: type nullable response properties as T | null

1 participant