TypeScript Code Generation

paradox generate --typescript [--path PATH]

Product Types

Input:

type Person
  name: Text
  age: Integer
  admin: Boolean

Output:

export interface Person {
  name: string;
  age: number;
  admin: boolean;
}

Union Types

Input:

union Cheese
  farmers
  cheddar
  brie: Text

Output:

export type Cheese = "farmers" | "cheddar" | [ "brie", string ]

Nullary tags become string literals. Tags with payloads become tagged tuples [tag, value].

Wrap Types

Wrap types generate branded types for nominal type safety:

Input:

wrap Natural: Integer

Output uses TypeScript’s structural typing with a branded phantom field to prevent accidental interchangeability.

Validators

Every type gets a validator function:

export const validPerson = (input: unknown): Person => {
  const _x = input as globalThis.Record<string, unknown>;
  if (_x.name === undefined) throw new Error('`_x.name` required but not present');
  if (typeof _x.name != 'string') throw new Error('`_x.name` must be a string');
  if (_x.age === undefined) throw new Error('`_x.age` required but not present');
  _x.age = parseInt(_x.age as string);
  if (typeof _x.age != 'number') throw new Error('`_x.age` must be a number');
  if(_x.admin === undefined) _x.admin = false;
  else if((_x.admin as unknown) === 'on') _x.admin = true;
  if (_x.admin === undefined) throw new Error('`_x.admin` required but not present');
  if (typeof _x.admin != 'boolean') throw new Error('`_x.admin` must be a boolean');
  const x = input as Person;
  const errors: string[] = [];
  if (errors.length > 0) throw new Error(errors.join('; '));
  return x;
}

export const isValidPerson = (input: unknown): boolean => {
  let ret = true;
  try { validPerson(input) } catch(err) { ret = false; }
  return ret;
}

Validators:

  • Accept unknown input for safe parsing

  • Check field presence and types

  • Coerce HTML form values (checkbox "on"true, string → parseInt)

  • Accumulate custom validation errors

  • Return the typed value or throw

Union Validators

export const validCheese = (x: unknown): Cheese => {
  const v = x as [string, unknown] | string;
  if((v != 'farmers') && (v != 'cheddar')
    && (v[0] === 'brie' && typeof v[1] != 'string')
    && (v[0] != 'brie'))
    throw new Error('Invalid Cheese `' + JSON.stringify(x) + '`');
  return x as Cheese;
}

Source Maps

TypeScript output includes .ts.map source map files for debugging back to the original .dox source.