Skip to content

type system: formalize 'string | null' (nullable string) with proper narrowing — unblocks clean FFI #599

@cs01

Description

@cs01

Summary

ChadScript's type system supports union types (per chadscript.d.ts: "Union Types — string | number support"), but string | null (nullable string) is not formalized as a first-class pattern with proper narrowing. This bites FFI and any code that needs "maybe-a-value" semantics.

Why it matters

Every library that calls C code hits this. C convention: return NULL to mean "no value" / "error". Currently chad's only options are:

  1. Coerce NULL → "" (lossy — can't distinguish "unset" from "empty string"; see ffi: NULL char* does not reliably round-trip to empty string in TS #591)
  2. Add a separate probe function (isOpen(), hasValue()) on every wrapper

Neither is ergonomic for user code. string | null with TypeScript-style narrowing (if (x !== null) { x.foo() }) is the right shape.

What "support" means concretely

  1. string | null as a valid type annotation that typechecks and compiles
  2. Null-literal assignment: const x: string | null = null;
  3. Narrowing: after if (x !== null), x has type string and methods work
  4. FFI bridge returns with i8* declared as string | null map NULL → null, non-null → string
  5. const empty: string = ""; const missing: string | null = null; empty === missing → false

Why it's probably already near-implemented

Chad has union types, narrowing patterns for other unions, and NaN/tagged sentinel infrastructure for JS-compatible null/undefined. The pieces exist. The question is whether string | null specifically round-trips cleanly through the type system and codegen.

Impact

Unblocks:

  • Cleaner FFI surface for every C library wrapper
  • Optional return values from user code (function lookup(key: string): Record | null)
  • Eliminates the isOpen() / hasValue() probe pattern from lib/net.ts, future Postgres driver, etc.
  • Better TypeScript compatibility (nullable types are ubiquitous in real TS code)

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions