Generate Typescript types from Golang source code

🎑 tygo

Tygo is a tool for generating Typescript typings from Golang source files that just works.

Other than reflection-based methods it preserves comments, understands constants and also supports non-struct type expressions. It's perfect for generating equivalent types for a Golang REST API to be used in your front-end codebase.

🚀 Now supports Golang 1.18 generic types

Installation

# Go >= 1.17
go install github.com/gzuidhof/tygo@latest
# Go < 1.17:
go install github.com/gzuidhof/tygo

Example

Golang input file

// Comments are kept :)
type ComplexType map[string]map[uint16]*uint32

type UserRole = string
const (
	UserRoleDefault UserRole = "viewer"
	UserRoleEditor  UserRole = "editor" // Line comments are also kept
)

type UserEntry struct {
	// Instead of specifying `tstype` we could also declare the typing
	// for uuid.NullUUID in the config file.
	ID uuid.NullUUID `json:"id" tstype:"string | null"`

	Preferences map[string]struct {
		Foo uint32 `json:"foo"`
		// An unknown type without a `tstype` tag or mapping in the config file
		// becomes `any`
		Bar uuid.UUID `json:"bar"`
	} `json:"prefs"`

	MaybeFieldWithStar *string  `json:"address"`
	Nickname           string   `json:"nickname,omitempty"`
	Role               UserRole `json:"role"`

	Complex    ComplexType `json:"complex"`
	unexported bool        // Unexported fields are omitted
	Ignored    bool        `tstype:"-"` // Fields with - are omitted too
}

type ListUsersResponse struct {
	Users []UserEntry `json:"users"`
}

Typescript output

/**
 * Comments are kept :)
 */
export type ComplexType = {
  [key: string]: { [key: number /* uint16 */]: number /* uint32 */ | undefined };
};
export type UserRole = string;
export const UserRoleDefault: UserRole = "viewer";
export const UserRoleEditor: UserRole = "editor"; // Line comments are also kept
export interface UserEntry {
  /**
   * Instead of specifying `tstype` we could also declare the typing
   * for uuid.NullUUID in the config file.
   */
  id: string | null;
  prefs: {
    [key: string]: {
      foo: number /* uint32 */;
      /**
       * An unknown type without a `tstype` tag or mapping in the config file
       * becomes `any`
       */
      bar: any /* uuid.UUID */;
    };
  };
  address?: string;
  nickname?: string;
  role: UserRole;
  complex: ComplexType;
}
export interface ListUsersResponse {
  users: UserEntry[];
}

For a real baptism by fire example, here is a Gist with output for the Go built-in net/http and time package.

Usage

Option A: CLI (recommended)

Create a file tygo.yaml in which you specify which packages are to be converted and any special type mappings you want to add.

packages:
  - path: "github.com/gzuidhof/tygo/examples/bookstore"
    type_mappings:
      time.Time: "string /* RFC3339 */"
      null.String: "null | string"
      null.Bool: "null | boolean"
      uuid.UUID: "string /* uuid */"
      uuid.NullUUID: "null | string /* uuid */"

Then run

tygo generate

The output Typescript file will be next to the Go source files.

Option B: Library-mode

config := &tygo.Config{
  Packages: []*tygo.PackageConfig{
      &tygo.PackageConfig{
          Path: "github.com/gzuidhof/tygo/examples/bookstore",
      },
  },
}
gen := tygo.New(config)
err := gen.Generate()

Config

# You can specify more than one package
packages:
  # The package path just like you would import it in Go
  - path: "github.com/my/package"

    # Where this output should be written to.
    # If you specify a folder it will be written to a file `index.ts` within that folder. By default it is written into the Golang package folder.
    output_path: "webapp/api/types.ts"

    # Customize the indentation (use \t if you want tabs)
    indent: "    "

    # Specify your own custom type translations, useful for custom types, `time.Time` and `null.String`.
    # Be default unrecognized types will be `any`.
    type_mappings:
      time.Time: "string"
      my.Type: "SomeType"

    # This content will be put at the top of the output Typescript file, useful for importing custom types.
    frontmatter: |
      "import {SomeType} from "../lib/sometype.ts"

    # Filenames of Go source files that should not be included
    # in the output.
    exclude_files:
      - "private_stuff.go"

See also the source file tygo/config.go.

Type hints through tagging

You can tag struct fields with tstype to specify their output Typescript type.

Custom type mapping

// Golang input

type Book struct {
	Title    string    `json:"title"`
	Genre    string    `json:"genre" tstype:"'novel' | 'crime' | 'fantasy'"`
}
// Typescript output

export interface Book {
  title: string;
  genre: "novel" | "crime" | "fantasy";
}

Alternative

You could use the frontmatter field in the config to inject export type Genre = "novel" | "crime" | "fantasy" at the top of the file, and use tstype:"Genre". I personally prefer that as we may use the Genre type more than once.

Required fields

Pointer type fields usually become optional in the Typescript output, but sometimes you may want to require it regardless.

You can add ,required to the tstype tag to mark a pointer type as required.

// Golang input
type Nicknames struct {
	Alice   *string `json:"alice"`
	Bob     *string `json:"bob" tstype:"BobCustomType,required"`
	Charlie *string `json:"charlie" tstype:",required"`
}
// Typescript output
export interface Nicknames {
  alice?: string;
  bob: BobCustomType;
  charlie: string;
}

Generics

Tygo supports generic types (Go version >= 1.18) out of the box.

// Golang input
type UnionType interface {
	uint64 | string
}

type ABCD[A, B string, C UnionType, D int64 | bool] struct {
	A A `json:"a"`
	B B `json:"b"`
	C C `json:"c"`
	D D `json:"d"`
}
// Typescript output
export type UnionType = 
    number /* uint64 */ | string
;

export interface ABCD<A extends string, B extends string, C extends UnionType, D extends number /* int64 */ | boolean> {
  a: A;
  b: B;
  c: C;
  d: D;
}

Related projects

  • typescriptify-golang-structs: Probably the most popular choice. The issue with this package is that it relies on reflection rather than parsing, which means that certain things can't be kept such as comments. The CLI generates Go file which is then executed and reflected on, and its library requires you to manually specify all types that should be converted.
  • go2ts: A transpiler with a web interface, this project was based off this project. It's perfect for quick one-off transpilations. There is no CLI, no support for const and there are no ways to customize the output.

License

MIT

Owner
Guido Zuidhof
I like making stuff that just works.
Guido Zuidhof
Comments
  • Pointer types always translated as optional variables

    Pointer types always translated as optional variables

    I noticed that pointers are always translated to TS using ?.

    For example:

    type FollowerEvent struct {
    	Follower            *twitter.User `json:"follower"`
    }
    

    Becomes:

    export interface FollowerEvent {
      follower?: any /* twitter.User */;
    }
    

    While it's true that pointers are often used to express optional values, they're also used for e.g. efficiency reasons and the value might be "guaranteed" to be set.

    Is there any way to remove the ? for pointer types from the generated TS?

  • TypeScript enum support

    TypeScript enum support

    Hello. Awesome package :) Quick question. Are you planning to support TypeScript enums? These can be transformed to TS enums.

    type UserRole = string
    const (
    	UserRoleDefault UserRole = "viewer"
    	UserRoleEditor  UserRole = "editor" // Line comments are also kept
    )
    

    Thanks Peter

  • Allow to ignore struct fields with tstype:

    Allow to ignore struct fields with tstype:"-"

    Similar to json:"-".

    In one of my projects, there's a field with a json tag that I don't want to expose via TypeScript. This PR makes that possible.

  • add support for immutable TypeScript fields

    add support for immutable TypeScript fields

    Just a small thing that came up when I was generating some REST response types that I wanted to be immutable.

    Add ,readonly to tstype tags and the field will be prefaced with the readonly keyword.

  • Add Go 1.18 generics support

    Add Go 1.18 generics support

    This PR adds support for Typescript code generation for Go code containing generics.

    Example one

    // Golang input
    type UnionType interface {
    	uint64 | string
    }
    
    type ABCD[A, B string, C UnionType, D int64 | bool] struct {
    	A A `json:"a"`
    	B B `json:"b"`
    	C C `json:"c"`
    	D D `json:"d"`
    }
    
    
    
    // Typescript output
    export type UnionType = 
        number /* uint64 */ | string
    ;
    
    export interface ABCD<A extends string, B extends string, C extends UnionType, D extends number /* int64 */ | boolean> {
      a: A;
      b: B;
      c: C;
      d: D;
    }
    

    Example two

    With a narrowed down type argument in a struct 🚀

    type Foo[A string | uint64, B *A] struct {
    	Bar A
    	Boo B
    }
    type WithFooGenericTypeArg[A Foo[string, *string]] struct {
    	SomeField A `json:"some_field"`
    }
    
    export interface Foo<A extends string | number /* uint64 */, B extends (A | undefined)> {
      Bar: A;
      Boo: B;
    }
    export interface WithFooGenericTypeArg<A extends Foo<string, string | undefined>> {
      some_field: A;
    }
    
Related tags
protoc-gen-grpc-gateway-ts is a Typescript client generator for the grpc-gateway project. It generates idiomatic Typescript clients that connect the web frontend and golang backend fronted by grpc-gateway.

protoc-gen-grpc-gateway-ts protoc-gen-grpc-gateway-ts is a Typescript client generator for the grpc-gateway project. It generates idiomatic Typescript

Dec 19, 2022
Generate types and service clients from protobuf definitions annotated with http rules.

protoc-gen-typescript-http Generates Typescript types and service clients from protobuf definitions annotated with http rules. The generated types fol

Nov 22, 2022
gRPC Web implementation for Golang and TypeScript

gRPC-Web: Typed Frontend Development gRPC is a modern, HTTP2-based protocol, that provides RPC semantics using the strongly-typed binary data format o

Dec 29, 2022
A simple FTP protocol with client and server implemented in TypeScript and Golang

websocket-ftp A simple FTP protocol with client and server implemented in TypeScript and Golang. Example (Client) const buffer: Uint8Array = (new Text

Apr 14, 2022
Transform Golang `enum` type to Typescript enum

golang-enum-to-ts Transform Golang enum type to Typescript enum Function Before (Golang) package some type Status int const ( Todo Status = iota D

Mar 1, 2022
Group peer to peer video calls for everyone written in Go and TypeScript

Peer Calls v4 WebRTC peer to peer calls for everyone. See it live in action at peercalls.com. The server has been completely rewriten in Go and all th

Dec 30, 2022
Example of strongly typed go/graphql/typescript web application

go-gql-typescript-example Example of strongly typed go/graphql/typescript web application Overview This is an example web application. On the server i

May 27, 2022
The high-performance build system for JavaScript & TypeScript codebases
The high-performance build system for JavaScript & TypeScript codebases

Documentation Visit https://turborepo.org to view the full documentation. Community To chat with other community members, you can join the Turborepo D

Jan 4, 2023
Read k8S-source-code notes, help quickly understand the K8S-code organization rules
Read k8S-source-code notes, help quickly understand the K8S-code organization rules

K8S源码阅读笔记 以下笔记针对 kubernetes V1.23.1(截至2022年01月01日最新版本),并不保证对其它版本的有效性 一、架构图 二、阅读前准备 由于kubernetes项目巧妙的设计和代码高度的封装性,建议在阅读代码前,尽可能的进行以下内容的准备: 1. 编程知识配备 编程语准

Feb 16, 2022
Useful collection functions for golang, based on generic types

go-collection English | 简体中文 go-collection provides developers with a convenient set of functions for working with common slices, maps, and arrays dat

Jul 21, 2022
Generate Server and Client side code

Additional Information Generate Server and Client side code Pre-generated stub file is included in the go project. If you need to generate the stub fi

Nov 6, 2021
Protoc plugin used to generate go-kit grpc code

protoc-gen-gokit-endpoint protoc plugin used to generate go-kit grpc code 安装 go install github.com/wwbweibo/protoc-gen-gokit-endpoint/cmd/protoc-gen-g

Sep 29, 2022
Protoc plugin used to generate go-kit grpc code

protoc-gen-gokit-endpoint protoc plugin used to generate go-kit grpc code 安装 go

Sep 29, 2022
Network address types

netaddr What This is a package containing a new IP address type for Go. See its docs: https://pkg.go.dev/inet.af/netaddr Motivation See https://tailsc

Dec 28, 2022
DeepCopy a portable app that allows you to copy all forms of specified file types from your entire file system of the computer

DeepCopy a portable app that allows you to copy all forms of specified file types from your entire file system of the computer

Dec 20, 2021
The source code, deployment manifests and CI/CD pipelines for the taxi application

The Taxi App About This repository contains the source code, deployment manifests and CI/CD pipelines for the taxi application. Application Source cod

Dec 11, 2021
Source Code for 'Pro Go' by Adam Freeman

Apress Source Code This repository accompanies Pro Go by Adam Freeman (Apress, 2022). Download the files as a zip using the green button, or clone the

Jan 1, 2023