Converts Cue types to TypeScript types and vice-versa.

  • By Inngest
  • Last update: Dec 8, 2022
  • Comments: 3

Cue + TypeScript


This package converts Cue types to TypeScript types, and soon vice-versa.

Cue is a concise language for defining types and constraints in one file. It's best practice to have a single source of truth for your types. This package allows you to convert your Cue types to TypeScript for the frontend.

Usage

This is a library for converting cue types, intended for use within a go application. Run the following command to install the package:

go get github.com/inngest/cuetypescript

Examples

CUE TypeScript
#Post: {
	id:        string
	slug:      string
	title:     string
	subtitle?: string
	rating:    float & <=5
	category:  "tech" | "finance" | "hr"
	tags: [...string]
	references: [...{
		slug:  string
		title: string
	}]
}
export const Category = {
  TECH: "tech",
  FINANCE: "finance",
  HR: "hr",
} as const;
export type Category = typeof Category[keyof typeof Category];

export interface Post {
  id: string;
  slug: string;
  title: string;
  subtitle?: string;
  rating: number;
  category: Category;
  tags: Array<string>;
  references: Array<{
    slug: string;
    title: string;
  }>;
};

Features

  • Interface generation
  • Type conversion and support
  • Nested struct support
  • Union support
  • "Best practice" enum generation. We create enums with both const and type values, allowing you to properly reference enum values via eg. Category.TECH.

In the future, we plan on adding:

  • Function generation for checking and validating Cue constraints
  • Default value generation and constructors
  • Typescript to Cue support

Download

cuetypescript.zip

Comments(3)

  • 1

    Title case enum names generated from struct names

    Tidies our generated names:

    evt: {
      some_enum: "a" | "b";
    }
    

    becomes:

    export const SomeEnum = {
      A: "a",
      B: "b",
    };
    export type SomeEnum = typeof SomeEnum[keyof typeof SomeEnum];
    

    Previously the name was Some_enum which, uh, sucked.

  • 2

    Always inline enum types

    Builds on #1.

    Previously, we only inline enums if all values are a type:

    evt: {
    	// null is treated as a type in TS
    	foo: string | null
    	bar: string | "baz"
    }
    

    This generated:

    export type Bar = string | "baz";
    
    export interface Evt {
      foo: string | null;
      bar: Bar;
    };
    

    With this PR we now generate:

    export interface Evt {
      foo: string | null;
      bar: string | "baz";
    };
    

    Note that enums containing values are still pulled out into top level consts:

    export const Category = {
      TECH: "tech",
      FINANCE: "finance",
      HR: "hr",
    } as const;
    export type Category = typeof Category[keyof typeof Category];
    
  • 3

    Add full support for null in enums, and inline scalar enums

    This PR adds support for enums with null values:

    {
    	foo: string | null
    }
    

    And it inlines enums in struct definitions if the enum contains only types:

    data: {
    	// the key is always present, but may be null
    	name: string | null
    }
    

    generates:

    export interface Data {
      name: string | null;
    };