{"id":16506107,"url":"https://github.com/gzuidhof/tygo","last_synced_at":"2025-05-15T00:07:18.545Z","repository":{"id":41158421,"uuid":"465503199","full_name":"gzuidhof/tygo","owner":"gzuidhof","description":"Generate Typescript types from Golang source code","archived":false,"fork":false,"pushed_at":"2025-03-10T10:19:09.000Z","size":117,"stargazers_count":706,"open_issues_count":9,"forks_count":52,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-13T20:41:13.058Z","etag":null,"topics":["codegen","golang","types","typescript"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gzuidhof.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"gzuidhof","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2022-03-02T23:35:19.000Z","updated_at":"2025-04-11T21:29:41.000Z","dependencies_parsed_at":"2024-03-05T12:25:42.787Z","dependency_job_id":"29581d06-0f64-482a-a8c6-94eae7e81bd3","html_url":"https://github.com/gzuidhof/tygo","commit_stats":{"total_commits":79,"total_committers":17,"mean_commits":4.647058823529412,"dds":0.5569620253164558,"last_synced_commit":"421f048c0ba2528d2cebe50fb8dbf3b0b5e36aac"},"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gzuidhof%2Ftygo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gzuidhof%2Ftygo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gzuidhof%2Ftygo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gzuidhof%2Ftygo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gzuidhof","download_url":"https://codeload.github.com/gzuidhof/tygo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254249197,"owners_count":22039029,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["codegen","golang","types","typescript"],"created_at":"2024-10-11T15:17:04.831Z","updated_at":"2025-05-15T00:07:13.533Z","avatar_url":"https://github.com/gzuidhof.png","language":"Go","funding_links":["https://github.com/sponsors/gzuidhof"],"categories":[],"sub_categories":[],"readme":"# 🎑 tygo\n\nTygo is a tool for generating Typescript typings from Golang source files that just works.\n\nIt 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.\n\n**🚀 Supports Golang 1.18 generic types and struct inheritance**\n\n## Installation\n\n```shell\ngo install github.com/gzuidhof/tygo@latest\n```\n\n## Example\n\n_Golang input file_\n\n```go\n// Comments are kept :)\ntype ComplexType map[string]map[uint16]*uint32\n\ntype UserRole = string\nconst (\n\tUserRoleDefault UserRole = \"viewer\"\n\tUserRoleEditor  UserRole = \"editor\" // Line comments are also kept\n)\n\ntype UserEntry struct {\n\t// Instead of specifying `tstype` we could also declare the typing\n\t// for uuid.NullUUID in the config file.\n\tID uuid.NullUUID `json:\"id\" tstype:\"string | null\"`\n\n\tPreferences map[string]struct {\n\t\tFoo uint32 `json:\"foo\"`\n\t\t// An unknown type without a `tstype` tag or mapping in the config file\n\t\t// becomes `any`\n\t\tBar uuid.UUID `json:\"bar\"`\n\t} `json:\"prefs\"`\n\n\tMaybeFieldWithStar *string  `json:\"address\"`\n\tNickname           string   `json:\"nickname,omitempty\"`\n\tRole               UserRole `json:\"role\"`\n  CreatedAt          time.Time `json:\"created_at,omitzero\"`\n\n\tComplex    ComplexType `json:\"complex\"`\n\tunexported bool        // Unexported fields are omitted\n\tIgnored    bool        `tstype:\"-\"` // Fields with - are omitted too\n}\n\ntype ListUsersResponse struct {\n\tUsers []UserEntry `json:\"users\"`\n}\n```\n\n_Typescript output_\n\n```typescript\n/**\n * Comments are kept :)\n */\nexport type ComplexType = {\n  [key: string]: {\n    [key: number /* uint16 */]: number /* uint32 */ | undefined;\n  };\n};\nexport type UserRole = string;\nexport const UserRoleDefault: UserRole = \"viewer\";\nexport const UserRoleEditor: UserRole = \"editor\"; // Line comments are also kept\nexport interface UserEntry {\n  /**\n   * Instead of specifying `tstype` we could also declare the typing\n   * for uuid.NullUUID in the config file.\n   */\n  id: string | null;\n  prefs: {\n    [key: string]: {\n      foo: number /* uint32 */;\n      /**\n       * An unknown type without a `tstype` tag or mapping in the config file\n       * becomes `any`\n       */\n      bar: any /* uuid.UUID */;\n    };\n  };\n  address?: string;\n  nickname?: string;\n  role: UserRole;\n  created_at?: string /* RFC3339 */;\n  complex: ComplexType;\n}\nexport interface ListUsersResponse {\n  users: UserEntry[];\n}\n```\n\nFor a real baptism by fire example, [here is a Gist with output for the Go built-in `net/http` and `time` package](https://gist.github.com/gzuidhof/7e192a2f33d8a4f5bde5b77fb2c5048c).\n\n## Usage\n\n### Option A: CLI (recommended)\n\nCreate a file `tygo.yaml` in which you specify which packages are to be converted and any special type mappings you want to add.\n\n```yaml\npackages:\n  - path: \"github.com/gzuidhof/tygo/examples/bookstore\"\n    type_mappings:\n      time.Time: \"string /* RFC3339 */\"\n      null.String: \"null | string\"\n      null.Bool: \"null | boolean\"\n      uuid.UUID: \"string /* uuid */\"\n      uuid.NullUUID: \"null | string /* uuid */\"\n```\n\nThen run\n\n```shell\ntygo generate\n```\n\nThe output Typescript file will be next to the Go source files.\n\n### Option B: Library-mode\n\n```go\nconfig := \u0026tygo.Config{\n  Packages: []*tygo.PackageConfig{\n      \u0026tygo.PackageConfig{\n          Path: \"github.com/gzuidhof/tygo/examples/bookstore\",\n      },\n  },\n}\ngen := tygo.New(config)\nerr := gen.Generate()\n```\n\n## Config\n\n```yaml\n# You can specify default mappings that will apply to all packages.\ntype_mappings:\n  time.Time: \"string /* RFC3339 */\"\n  \n# You can specify more than one package\npackages:\n  # The package path just like you would import it in Go\n  - path: \"github.com/my/package\"\n\n    # Where this output should be written to.\n    # 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.\n    output_path: \"webapp/api/types.ts\"\n\n    # Customize the indentation (use \\t if you want tabs)\n    indent: \"    \"\n\n    # Specify your own custom type translations, useful for custom types, `time.Time` and `null.String`.\n    # By default unrecognized types will be `any`.\n    # A mapping specified here will override one specified globally.\n    type_mappings:\n      time.Time: \"string\"\n      my.Type: \"SomeType\"\n\n    # This content will be put at the top of the output Typescript file, useful for importing custom types.\n    frontmatter: |\n      \"import {SomeType} from \"../lib/sometype.ts\"\n\n    # Filenames of Go source files that should not be included\n    # in the output.\n    exclude_files:\n      - \"private_stuff.go\"\n\n    # Package that the generates Typescript types should extend. This is useful when\n    # attaching your types to a generic ORM.\n    extends: \"SomeType\"\n```\n\nSee also the source file [tygo/config.go](./tygo/config.go).\n\n## Type hints through tagging\n\nYou can tag struct fields with `tstype` to specify their output Typescript type.\n\n### Custom type mapping\n\n```golang\n// Golang input\n\ntype Book struct {\n\tTitle    string    `json:\"title\"`\n\tGenre    string    `json:\"genre\" tstype:\"'novel' | 'crime' | 'fantasy'\"`\n}\n```\n\n```typescript\n// Typescript output\n\nexport interface Book {\n  title: string;\n  genre: \"novel\" | \"crime\" | \"fantasy\";\n}\n```\n\n**Alternative**\n\nYou 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.\n\n**`tygo:emit` directive**\n\nAnother way to generate types that cannot be directly represented in Go is to use a `//tygo:emit` directive to \ndirectly emit literal TS code.\nThe directive can be used in two ways. A `tygo:emit` directive on a struct will emit the remainder of the directive \ntext before the struct.\n```golang\n// Golang input\n\n//tygo:emit export type Genre = \"novel\" | \"crime\" | \"fantasy\"\ntype Book struct {\n\tTitle    string    `json:\"title\"`\n\tGenre    string    `json:\"genre\" tstype:\"Genre\"`\n}\n```\n\n```typescript\nexport type Genre = \"novel\" | \"crime\" | \"fantasy\"\n\nexport interface Book {\n  title: string;\n  genre: Genre;\n}\n```\n\nA `//tygo:emit` directive on a string var will emit the contents of the var, useful for multi-line content.\n```golang\n//tygo:emit\nvar _ = `export type StructAsTuple=[\n  a:number, \n  b:number, \n  c:string,\n]\n`\ntype CustomMarshalled struct {\n  Content []StructAsTuple `json:\"content\"`\n}\n```\n\n```typescript\nexport type StructAsTuple=[\n  a:number, \n  b:number, \n  c:string,\n]\n\nexport interface CustomMarshalled {\n  content: StructAsTuple[];\n}\n\n```\n\nGenerating types this way is particularly useful for tuple types, because a comma cannot be used in the `tstype` tag.\n\n### Required fields\n\nPointer type fields usually become optional in the Typescript output, but sometimes you may want to require it regardless.\n\nYou can add `,required` to the `tstype` tag to mark a pointer type as required.\n\n```golang\n// Golang input\ntype Nicknames struct {\n\tAlice   *string `json:\"alice\"`\n\tBob     *string `json:\"bob\" tstype:\"BobCustomType,required\"`\n\tCharlie *string `json:\"charlie\" tstype:\",required\"`\n}\n```\n\n```typescript\n// Typescript output\nexport interface Nicknames {\n  alice?: string;\n  bob: BobCustomType;\n  charlie: string;\n}\n```\n\n### Readonly fields\n\nSometimes a field should be immutable, you can add `,readonly` to the `tstype` tag to mark a field as `readonly`.\n\n```golang\n// Golang input\ntype Cat struct {\n\tName    string `json:\"name,readonly\"`\n\tOwner   string `json:\"owner\"`\n}\n```\n\n```typescript\n// Typescript output\nexport interface Cat {\n  readonly name: string;\n  owner: string;\n}\n```\n\n## Inheritance\n\nTygo supports interface inheritance. To extend an `inlined` struct, use the tag `tstype:\",extends\"` on struct fields you wish to extend. Only `struct` types can be extended.\n\nStruct pointers are optionally extended using `Partial\u003cMyType\u003e`. To mark these structs as required, use the tag `tstype:\",extends,required\"`.\n\nNamed `struct fields` can also be extended.\n\nExample usage [here](examples/inheritance)\n\n```go\n// Golang input\nimport \"example.com/external\"\n\ntype Base struct {\n\tName string `json:\"name\"`\n}\n\ntype Base2[T string | int] struct {\n\tID T `json:\"id\"`\n}\n\ntype OptionalPtr struct {\n\tField string `json:\"field\"`\n}\n\ntype Other[T int] struct {\n\t*Base                  `       tstype:\",extends,required\"`\n\tBase2[T]               `       tstype:\",extends\"`\n\t*OptionalPtr           `       tstype:\",extends\"`\n\texternal.AnotherStruct `       tstype:\",extends\"`\n\tOtherValue             string `                  json:\"other_value\"`\n}\n```\n\n```typescript\n// Typescript output\nexport interface Base {\n  name: string;\n}\n\nexport interface Base2\u003cT extends string | number /* int */\u003e {\n  id: T;\n}\n\nexport interface OptionalPtr {\n  field: string;\n}\n\nexport interface Other\u003cT extends number /* int */\u003e\n  extends Base,\n    Base2\u003cT\u003e,\n    Partial\u003cOptionalPtr\u003e,\n    external.AnotherStruct {\n  other_value: string;\n}\n```\n\n## Generics\n\nTygo supports generic types (Go version \u003e= 1.18) out of the box.\n\n```go\n// Golang input\ntype UnionType interface {\n\tuint64 | string\n}\n\ntype ABCD[A, B string, C UnionType, D int64 | bool] struct {\n\tA A `json:\"a\"`\n\tB B `json:\"b\"`\n\tC C `json:\"c\"`\n\tD D `json:\"d\"`\n}\n```\n\n```typescript\n// Typescript output\nexport type UnionType = number /* uint64 */ | string;\n\nexport interface ABCD\u003c\n  A extends string,\n  B extends string,\n  C extends UnionType,\n  D extends number /* int64 */ | boolean\n\u003e {\n  a: A;\n  b: B;\n  c: C;\n  d: D;\n}\n```\n\n## YAML support\n\nTygo supports generating typings for YAML-serializable objects that can be understood by Go apps.\n\nBy default, Tygo will respect `yaml` Go struct tags, in addition to `json`, but it will not apply any transformations to untagged fields.\nHowever, the default behavior of the popular `gopkg.in/yaml.v2` package for Go structs without tags is to downcase the struct field names.\nTo emulate this behavior, one can use the `flavor` configuration option:\n\n```yaml\npackages:\n  - path: \"github.com/my/package\"\n    output_path: \"webapp/api/types.ts\"\n    flavor: \"yaml\"\n```\n\n```go\n// Golang input\ntype Foo struct {\n\tTaggedField string `yaml:\"custom_field_name_in_yaml\"`\n    UntaggedField string\n}\n```\n\n```typescript\n// Typescript output\nexport interface Foo {\n  custom_field_name_in_yaml: string;\n  untaggedfield: string;\n}\n```\n\n## Related projects\n\n- [**typescriptify-golang-structs**](https://github.com/tkrajina/typescriptify-golang-structs): Probably the most popular choice. The downside of this package is that it relies on reflection rather than parsing, which means that certain things can't be kept such as comments without adding a bunch of tags to your structs. The CLI generates a Go file which is then executed and reflected on. The library requires you to manually specify all types that should be converted.\n- [**go2ts**](https://github.com/StirlingMarketingGroup/go2ts): A transpiler with a web interface, this project can be seen as an evolution of 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.\n\n**If `tygo` is useful for your project, consider leaving a star.**\n\n## License\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgzuidhof%2Ftygo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgzuidhof%2Ftygo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgzuidhof%2Ftygo/lists"}