Value Objects
Typically value objects will be serialized / marshalled as JSON. Please refer to this documentation:
https://pkg.go.dev/encoding/json#Marshal
This is just a few basic examples, that show the basics of mapping Go types to idiomatic TypeScript types.
Scalar types
Supported in Go and TypeScript
Go | TypeScript |
---|---|
string | string |
bool | boolean |
Numerics / numbers
Go | TypeScript |
---|---|
int, int8, int16, float32, float64 ... | number |
Type Aliases
type Greeting string
type Greeting = string;
Enumerations
Go does not support enumerations, but gotsrpc
will translate constants to TypeScripts enums:
type Pet string
const (
Cat Pet = "cat"
Dog Pet = "dog"
Fish Pet = "fish"
)
type SeatCount int
const (
TwoSeats SeatCount = 2
FiveSeats SeatCount = 5
SevenSeats SeatCount = 7
)
export enum Pet {
Cat = "cat",
Dog = "dog",
Fish = "fish",
}
export enum SeatCount {
FiveSeats = 5,
SevenSeats = 7,
TwoSeats = 2,
}
Slices
Slices are nilable in Go, thus they can be null in TypeScript. They translate to Array<T>|null
in TypeScript.
Scalar types
[]string
[]int
// other numeric types
[]bool
Array<string> | null;
Array<number> | null;
// all numeric types are numbers
Array<boolean> | null;
Other slice type examples
Structs
[]Car
[]*Car
Array<Car> | null;
Array<Car | null> | null;
Nested slices
[][]string
[][]int
// ...
Array<Array<string> | null> | null;
Array<Array<number> | null> | null;
// ...
Maps / Records
Like slices Go maps are nilable. They translate to Record<K extends keyof any, T>|null
in TypeScript.
Scalars
map[string]string
Record<string, string> | null;
Structs
map[string]*Car
Record<string, Car | null> | null;
Slices
map[string][]*Car
Record<string, Array<Car | null> | null> | null;
Map types
Go and TypeScript support map / Record types:
Scalar types / type aliases are of particular value when using maps, because they can add strong semantics:
type CarDirectory map[ProductID]*Car
type CarDirectory = Record<ProductID, Car | null> | null;
Nested map types
type BrandID string
type BrandCarDirectory map[BrandID]map[ProductID]*Car
// or
type BrandCarDirectory map[BrandID]CarDirectory
type BrandID = string;
type BrandCarDirectory = Record<
BrandID,
Record<ProductID, Car | null> | null
> | null;
// or
type BrandCarDirectory = Record<BrandID, CarDirectory> | null;
Structs / Interfaces
Arbitrary Types can be composed in structs.
Field names
Naming conventions are different between Go and TypeScript. In order to bridge the gap between Go and TypeScript Go struct fields can be annotated with tags. In this way idiomatic naming of fields can be can be provided for both languages and the translation will be automatic.
Default Go => TypeScript
Without json tags TypeScript field names will be like in Go, which is not idiomatic for TypeScript.
type Car struct {
GoCase string
CamelCase string
SnakeCase string
}
interface Car {
GoCase:string;
CamelCase:string;
SnakeCase:string;
}
Idiomatic field names
Json tags allow controlling the name in TypeScript.
type Car struct {
CamelCase string `json:"camelCase"`
SnakeCase string `json:"snake_case"`
}
interface Car {
camelCase:string;
snake_case:string;
}
Optional and nullable fields
type Basic struct {
Value string `json:"value"`
OptionalValue string `json:"optionalValue,omitempty"`
NullableValue *string `json:"nullableValue"`
}
type Basic interface {
value:string;
optionalValue?:string;
nullableValue:string|null;
}
Hiding values from the client
The Go json tag `json:"-"`
on a struct allows it to:
- hide fields from clients
- prevents clients from setting them in JSON Unmarshalling
type Basic struct {
Value string `json:"value"`
Secret string `json:"-"`
}
type Basic interface {
value:string;
}
Union Types
When static types seem to be in the way
Scalars
type (
Species struct {
LandAnimals *LandAnimals `json:"landAnimals,omitempty" gotsrpc:"union"`
WaterAnimals *WaterAnimals `json:"waterAnimals,omitempty" gotsrpc:"union"`
}
LandAnimals string
WaterAnimals string
)
const (
Cat LandAnimals = "cat"
Dog LandAnimals = "dog"
)
const (
Catfish WaterAnimals = "catfish"
Dogfish WaterAnimals = "dogfish"
)
)
export enum WaterAnimals {
Catfish = "catfish",
Dogfish = "dogfish",
}
export enum LandAnimals {
Cat = "cat",
Dog = "dog",
}
export const Species = { ...github_com_foomo_gotsrpc_playground_server_services_wof.LandAnimals, ...github_com_foomo_gotsrpc_playground_server_services_wof.WaterAnimals }
export type Species = github_com_foomo_gotsrpc_playground_server_services_wof.LandAnimals | github_com_foomo_gotsrpc_playground_server_services_wof.WaterAnimals
Structs
type (
Trip struct {
Kind string `json:"kind" gotsrpc:"type:'Trip'"`
Destination string `json:"destination"`
}
Car struct {
Kind string `json:"kind" gotsrpc:"type:'Car'"`
Model string `json:"model"`
}
Pet struct {
Kind string `json:"kind" gotsrpc:"type:'Pet'"`
Name string `json:"name"`
}
Price struct {
Trip *Trip `json:"trip,omitempty" gotsrpc:"union"`
Car *Car `json:"car,omitempty" gotsrpc:"union"`
Pet *Pet `json:"pet,omitempty" gotsrpc:"union"`
}
)
export interface Trip {
kind:'Trip';
destination:string;
}
export interface Car {
kind:'Car';
model:string;
}
export interface Pet {
kind:'Pet';
name:string;
}
export type Price = github_com_foomo_gotsrpc_playground_server_services_wof.Trip | github_com_foomo_gotsrpc_playground_server_services_wof.Car | github_com_foomo_gotsrpc_playground_server_services_wof.Pet | undefined