Convert Golang structs to Typescript interfaces
Handle
omitempty
and inline
appropriatelyuuid.UUID
& time.Time
conversionexamples/5-generic-struct
)go get github.com/tompston/gut
package main
import (
"fmt"
"time"
"github.com/google/uuid"
"github.com/tompston/gut"
)
func main() {
// define which structs you want to convert
ex1 := gut.Convert(User{})
ex2 := gut.Convert(Comments{})
ex3 := gut.Convert(MyRandomStruct{})
// concat all of the interfaces together
interfaces := fmt.Sprintln(ex1, ex2, ex3)
if err := gut.Generate("./example.gen.ts",interfaces); err != nil {
fmt.Println(err)
}
}
type User struct {
ID uuid.UUID `json:"user_id"`
Username string `json:"username"`
CreatedAt time.Time `json:"created_at"`
Comments `json:"comments,omitempty"`
}
type Comments []struct {
ID int `json:"comment_id"`
Value string `json:"value"`
}
type MyRandomStruct struct {
MyFloat float64
MyInterface interface{}
Ex1 map[string]map[string]string
IntArray []int
}
export type UuidType = string;
export type BigIntType = BigInt;
export type DateType = Date;
export interface User {
user_id: UuidType;
username: string;
created_at: DateType;
comments?: {
comment_id: number;
value: string;
}[];
}
export type CommentsArray = Comments[];
export interface Comments {
comment_id: number;
value: string;
}
export interface MyRandomStruct {
MyFloat: number;
MyInterface: any;
Ex1: { [key: string]: { [key: string]: string } };
IntArray: number[];
}
To format the generated typescript code, you can run deno fmt .
I wanted to solve the problem of converting golang structs to typescript interfaces, so that the backend and frontend clients could be in-sync, but I found that the current packages which try to do this had bugs and did not have the features I wanted. So I had to write it from scratch (with some help from ChatGPT)
go test . -v -count=1
Handle cases when the convertable struct is an array
Handle json ",omitempty" tags
Handle json ",inline" tags (embeded structs)
examples/4-struct-with-inline
)handle uuid.UUID
& time.Time
conversion
Avoid duplicate interface names, by generating only one typescript interface which will hold all of the types that are present in the struct.
Flexible typescript type system for the converted time.Time
, uuid.UUID
and
int64
/ uint64
types.
optionally generate the type which holds an array of interfaces
Ability to optionally rename the generated typescript interface to a custom name
flexibility in exporting the converted go structs from packages
Convert()
returns a string which holds the generated typescriptKeep the package simple.
gut
exports only 2 funtions
Convert()
-> converts the struct into a ts stringGenerate()
-> save the converted ts interfaces to adeno fmt .
The initial draft of the code was generated by ChatGPT. After some heavy refactoring, this is the end result.
package main
import (
"fmt"
"time"
"github.com/google/uuid"
"github.com/tompston/gut"
)
func main() {
// Insetad of generating an interface called User,
// create one with a custom name
ex1 := gut.Convert(User{},
gut.Type{Name: "MyCustomInterface"})
// Generate both the interface for the struct and
// also a type which holds an array of interfaces.
// + optionally you can also rename it.
ex2 := gut.Convert(MyRandomStruct{},
gut.Type{IsArray: true, ArrayTypeName: "ArrayOfMyRandomStructs"})
// concat all of the interfaces together
interfaces := fmt.Sprintln(ex1, ex2)
if err := gut.Generate("./example.gen.ts", interfaces); err != nil {
fmt.Println(err)
}
}
type User struct {
ID uuid.UUID `json:"user_id"`
Username string `json:"username"`
CreatedAt time.Time `json:"created_at"`
Comments `json:"comments,omitempty"`
}
type Comments []struct {
ID int `json:"comment_id"`
Value string `json:"value"`
}
type MyRandomStruct struct {
MyFloat float64
MyInterface interface{}
Ex1 map[string]map[string]string `json:"ex_1"`
IntArray []int `json:"int_array"`
OptionalStringArray []string `json:"opt_str_array,omitempty"`
}
export type UuidType = string;
export type BigIntType = BigInt;
export type DateType = Date;
export interface MyCustomInterface {
user_id: UuidType;
username: string;
created_at: DateType;
comments?: {
comment_id: number;
value: string;
}[];
}
export type ArrayOfMyRandomStructs = MyRandomStruct[];
export interface MyRandomStruct {
MyFloat: number;
MyInterface: any;
ex_1: { [key: string]: { [key: string]: string } };
int_array: number[];
opt_str_array?: string[];
}
package main
import (
"fmt"
"time"
"github.com/google/uuid"
"github.com/tompston/gut"
)
func main() {
// Insetad of generating an interface called User,
// create one with a custom name
ex1 := gut.Convert(User{},
gut.Type{Name: "MyCustomInterface"})
if err := gut.Generate(
"./example.gen.ts", ex1, gut.Settings{
FirstLine: "// This is a custom comment in the file\n",
DateType: "string",
UuidType: "string",
BigIntType: "number",
}); err != nil {
fmt.Println(err)
}
}
type User struct {
ID uuid.UUID `json:"user_id"`
Username string `json:"username"`
CreatedAt time.Time `json:"created_at"`
}
// This is a custom comment in the file
export type UuidType = string;
export type BigIntType = number;
export type DateType = string;
export interface MyCustomInterface {
user_id: UuidType;
username: string;
created_at: DateType;
}