Converting CUE objects to their TypeScript equivalent (highly experimental!)
- CUE makes defining and validating canonical data specification easy
- TypeScript is dominant in the frontend, but cannot natively benefit from this
- CUE types have direct TypeScript equivalents, so cuetsy can bridge this gap
| CUE | TypeScript |
|---|---|
DiceFaces: 1 | 2 | 3 | 4 | 5 | 6 @cuetsy(targetType="type")
Animal: {
Name: string
Sound: string
} @cuetsy(targetType="interface")
LeggedAnimal: Animal & {
Legs: int
} @cuetsy(targetType="interface")
Pets: "Cat" | "Dog" | "Horse" @cuetsy(targetType="enum") |
export type DiceFaces = 1 | 2 | 3 | 4 | 5 | 6;
export interface Animal {
Name: string;
Sound: string;
}
export interface LeggedAnimal extends Animal {
Legs: number;
}
export enum Pets {
Cat = "Cat",
Dog = "Dog",
Horse = "Horse",
} |
Cuetsy is in its early development, so it does not support all TypeScript features. However, the following are supported:
- Types
- Default
const
Cuetsy can be installed using Go 1.16+
$ go install github.com/sdboyer/cuetsy/cmd/cuetsycuetsy must be invoked on files as follows:
$ cuetsy [file.cue]This will create a logically equivalent [file].ts
| CUE | TypeScript | @cuetsy(targetType) |
|---|---|---|
| Disjunction | Union Type | type |
Union types are expressed in CUE and TypeScript nearly the same way, namely a
series of disjunctions (a | b | c):
| CUE | TypeScript |
|---|---|
MyUnion: 1 | 2 | 3 | 4 | 5 | 6 @cuetsy(targetType="type") |
export type MyUnion = 1 | 2 | 3 | 4 | 5 | 6; |
| CUE | TypeScript | @cuetsy(targetType) |
|---|---|---|
| Struct | Interface | interface |
TypeScript interfaces are expressed as regular structs in CUE.
Caveats:
- Nested structs are not supported
| CUE | TypeScript |
|---|---|
MyInterface: {
Num: number
Text: string
List: [...number]
Truth: bool
} @cuetsy(targetType="interface") |
export interface MyInterface {
List: number[];
Num: number;
Text: string;
Truth: boolean;
} |
Interfaces can optionally inherit from another interface. This is expressed
using the union operator &:
| CUE | TypeScript |
|---|---|
AInterface: {
AField: string
} @cuetsy(targetType="interface")
BInterface: AInterface & {
BField: int
} @cuetsy(targetType="interface") |
export interface AInterface {
AField: string;
}
export interface BInterface extends AInterface {
BField: number;
} |
| CUE | TypeScript | @cuetsy(targetType) |
|---|---|---|
| Disjunction, Struct | Enum | enum |
Cuetsy supports two ways of expressing TypeScript enums in CUE:
Disjunctions may be used in a very similar way to Union Types. The keys of the enum are automatically inferred as the titled camel-case variant of their value:
| CUE | TypeScript |
|---|---|
MyEnum: "foo" | "bar" | "baz" @cuetsy(targetType="enum") |
export enum MyEnum {
Bar = "bar",
Baz = "baz",
Foo = "foo",
} |
If the implicit keys are insufficient, the struct based style gives more
control:
| CUE | TypeScript |
|---|---|
MyEnum: {
Foo: "foo"
iCanChoose: "whateverILike"
} @cuetsy(targetType="enum") |
export enum MyEnum {
Foo = "foo",
iCanChoose = "whateverILike",
} |
| CUE | TypeScript |
|---|---|
| Defaults | const |
Cuetsy can optionally generate a const for each type that holds default
values. For that, attach CUE Default
Values to your type
definitions:
| CUE | TypeScript |
|---|---|
MyUnion: 1 | 2 | *3 @cuetsy(targetType="type")
MyDisjEnum: "foo" | *"bar" @cuetsy(targetType="enum")
MyStructEnum: {
A: "Foo"
B: "Bar" @cuetsy(enumDefault)
} @cuetsy(targetType="enum")
MyInterface: {
num: int | *6
txt: string | *"CUE"
enm: MyDisjEnum
} @cuetsy(targetType="interface") |
export type MyUnion = 1 | 2 | 3;
export const myUnionDefault: MyUnion = 3;
export enum MyDisjEnum {
Bar = "bar",
Foo = "foo",
}
export const myDisjEnumDefault: MyDisjEnum = MyDisjEnum.Bar;
export enum MyStructEnum {
A = "Foo",
B = "Bar",
}
export const myStructEnumDefault: MyStructEnum = MyStructEnum.B;
export interface MyInterface {
enm: MyDisjEnum;
num: number;
txt: string;
}
export const myInterfaceDefault: MyInterface = {
enm: myDisjEnumDefault,
num: 6,
txt: "CUE",
}; |