{"id":11597,"library":"protoc-gen-ts","title":"Protocol Buffer Compiler for TypeScript","description":"protoc-gen-ts is a `protoc` plugin that generates plain TypeScript source files from Protocol Buffer `.proto` definitions, effectively replacing separate `.d.ts` declaration files. It is actively maintained, with the current stable version being `0.8.7`, and new features/fixes are delivered through frequent minor releases. A key differentiator is its direct TypeScript output which eliminates common prefixes (e.g., `getField`) and exposes fields as standard getters/setters, along with `fromObject` and `toObject` methods for robust bidirectional mapping between JSON and message instances, supporting deep structures without runtime type reflection. It offers native support for gRPC Node (`@grpc/grpc-js`) and gRPC Web, including options for promise-based RPC calls. Messages defined within a `package` directive in the `.proto` file are by default encapsulated within a TypeScript namespace, though this behavior can be toggled.","status":"active","version":"0.8.7","language":"javascript","source_language":"en","source_url":"https://github.com/thesayyn/protoc-gen-ts","tags":["javascript"],"install":[{"cmd":"npm install protoc-gen-ts","lang":"bash","label":"npm"},{"cmd":"yarn add protoc-gen-ts","lang":"bash","label":"yarn"},{"cmd":"pnpm add protoc-gen-ts","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Messages are generated as ES Modules. The path depends on your `--ts_out` setting and `package` name in your .proto file (e.g., `myproto_pb` if `package mypackage` is used, or `myproto` if no package).","wrong":"const { Change } = require('./myproto_pb');","symbol":"Change","correct":"import { Change } from './myproto_pb';"},{"note":"Enums are generated as named exports. The import path and filename reflect the proto file and package structure.","wrong":"import Kind from './myproto_pb';","symbol":"Kind","correct":"import { Kind } from './myproto_pb';"},{"note":"gRPC services generate a client class (e.g., `MyServiceClient`) and potentially an interface (e.g., `IMyService`). The exact name depends on the proto service definition.","wrong":"import { MyService } from './myproto_pb';","symbol":"MyService","correct":"import { MyServiceClient } from './myproto_pb';"}],"quickstart":{"code":"import { Change, Kind, Author } from './myproto_pb'; // Assumes protoc-gen-ts generated './myproto_pb.ts'\n\n// Construct a message instance\nconst author = new Author({\n    name: 'mary poppins',\n    role: 'maintainer'\n});\n\nconst change = new Change({\n    kind: Kind.UPDATED,\n    patch: '@@ -7,11 +7,15 @@',\n    tags: ['no prefix', 'as is'],\n    name: 'patch for typescript 4.5',\n    author: author\n});\n\n// Serialize to bytes (Uint8Array)\nconst bytes: Uint8Array = change.serialize();\n\nconsole.log('Serialized bytes:', bytes);\n\n// Deserialize from bytes back into a message instance\nconst receivedChange: Change = Change.deserialize(bytes);\n\nconsole.log('Deserialized Change object:', receivedChange);\nconsole.log('Kind:', receivedChange.kind === Kind.UPDATED); // true\nconsole.log('Author name:', receivedChange.author?.name); // mary poppins\n\n// Using fromObject for easier JSON-to-message mapping\nconst jsonChange = Change.fromObject({\n    kind: Kind.DELETED,\n    patch: 'deleted line',\n    tags: ['cleanup'],\n    id: '12345',\n    author: {\n        name: 'john doe',\n        role: 'contributor'\n    }\n});\n\nconsole.log('Change from JSON:', jsonChange.toObject());\nconsole.log('Author from JSON is an Author instance:', jsonChange.author instanceof Author);","lang":"typescript","description":"This quickstart demonstrates how to create, serialize, and deserialize a Protocol Buffer message using the generated TypeScript classes. It also illustrates the convenient `fromObject` and `toObject` methods for JSON interoperability."},"warnings":[{"fix":"Review code that checks for the presence of fields or relies on `undefined` for unset fields. Explicitly check for field presence if distinguishing between an unset field and a field with its default value is critical. For oneof fields, check the `oneof_name` property to determine which field is set.","message":"In version `0.8.5`, `getters` and `toObject` methods were changed to return the *default value* for a field if it is not present, instead of `undefined`. This affects behavior for optional fields, proto2 fields, and oneof fields that are not set, potentially requiring code adjustments if `undefined` or `null` checks were previously used.","severity":"breaking","affected_versions":">=0.8.5"},{"fix":"Consult the official `protoc-gen-ts` documentation or GitHub repository for updated Bazel integration guidelines and migration paths.","message":"The `index.bzl` file has been deprecated in version `0.8.7`. Users integrating with Bazel build systems may need to update their Bazel configurations to align with the new recommended practices for Bazel integration.","severity":"deprecated","affected_versions":">=0.8.7"},{"fix":"Use the `--ts_opt=no_namespace` option when running `protoc` to disable namespace generation and have all generated types in the global module scope (or their respective file modules).","message":"By default, `protoc-gen-ts` generates TypeScript namespaces corresponding to the `package` directive in your `.proto` files. If you prefer a flatter module structure or encounter issues with namespace resolution, this behavior can be altered.","severity":"gotcha","affected_versions":">=0.8.0"},{"fix":"Ensure `protoc-gen-ts` is installed globally (`npm install -g protoc-gen-ts`) and that its installation directory is in your system's PATH. Alternatively, you can explicitly provide the plugin path to `protoc` using `--plugin=protoc-gen-ts=/path/to/protoc-gen-ts`.","message":"`protoc-gen-ts` is a `protoc` plugin and must be discoverable by the `protoc` executable. If `protoc` cannot find the plugin, it will fail with an error indicating the program is not found.","severity":"gotcha","affected_versions":">=0.8.0"},{"fix":"If using gRPC functionality from generated code, ensure you have installed the appropriate gRPC runtime library: `npm install @grpc/grpc-js` for Node.js or include the necessary gRPC Web client libraries for browser environments.","message":"The package `protoc-gen-ts` itself does not have runtime npm dependencies beyond standard Node.js/TypeScript. However, the *generated code* often relies on runtime libraries for gRPC functionality (e.g., `@grpc/grpc-js` or `grpc`). These must be installed separately in your project if you generate gRPC service clients/servers.","severity":"gotcha","affected_versions":">=0.8.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Install `protoc-gen-ts` globally (`npm install -g protoc-gen-ts`) and ensure your PATH includes npm's global bin directory. Alternatively, specify the full path to the plugin: `protoc --plugin=protoc-gen-ts=$(which protoc-gen-ts) -I=...`.","cause":"The `protoc` compiler cannot locate the `protoc-gen-ts` executable in the system's PATH.","error":"protoc-gen-ts: program not found"},{"fix":"Verify that the `--ts_out` option in your `protoc` command points to the correct output directory. Ensure your `tsconfig.json` includes this directory in `include` or `files`, and that `baseUrl` and `paths` are configured correctly if you are using path aliases. Adjust import statements to match the actual generated file names and paths.","cause":"The TypeScript compiler cannot resolve the import path to the generated Protocol Buffer files, either due to incorrect path, missing `tsconfig.json` configuration, or the generated files not being in the include path.","error":"TS2307: Cannot find module './myproto_pb' or its corresponding type declarations."},{"fix":"Ensure the JSON object passed to `fromObject` strictly adheres to the structure of your `.proto` message definition, especially for nested messages and repeated fields. Verify all required fields are present and correctly typed.","cause":"This typically occurs when `fromObject` is called with an invalid or unexpected JSON structure, such as a missing nested object or an array where a single object is expected, and an attempt is made to access properties on `undefined`.","error":"TypeError: Cannot read properties of undefined (reading 'name') at Object.fromObject"},{"fix":"Check your `.proto` file for the exact field name. By default, fields are named as-is. If `json_names` option is enabled, check for camelCase. For `oneof` fields, access the field through the `oneof_name` property first. Ensure your TypeScript version is compatible (e.g., `ts-5` is allowed as a peer dep since `0.8.7`).","cause":"This can happen if you are trying to access a field using a name that does not match the generated TypeScript property, or if the field is part of a `oneof` and is not currently set, or if an older version of TypeScript is used that doesn't fully support certain generated constructs.","error":"TS2339: Property 'myField' does not exist on type 'MyMessage'."}],"ecosystem":"npm"}