Command-line utility for generating TypeScript type definitions from .proto files, enabling type-safe gRPC development in TypeScript projects.
The CLI tool generates TypeScript interface and type definitions from Protocol Buffer files.
proto-loader-gen-types [options] filenames...Installation and Usage:
# Install package
npm install @grpc/proto-loader
# Generate types
npx proto-loader-gen-types --longs=String --enums=String --defaults --oneofs --grpcLib=@grpc/grpc-js --outDir=proto/ proto/*.proto
# Or use directly from node_modules
$(npm bin)/proto-loader-gen-types --outDir=types/ service.proto| Option | Type | Default | Description |
|---|---|---|---|
--help | boolean | - | Show help information |
--version | boolean | - | Show version number |
--keepCase | boolean | false | Preserve the case of field names |
--longs | string | "Long" | The type for 64-bit integer values. Can be "String", "Number" |
--enums | string | "number" | The type for enum fields. Can be "String" |
--bytes | string | "Buffer" | The type for bytes fields. Can be "String", "Array" |
--defaults | boolean | false | Output default values for omitted fields |
--arrays | boolean | false | Output default values for omitted repeated fields even if --defaults is not set |
--objects | boolean | false | Output default values for omitted message fields even if --defaults is not set |
--oneofs | boolean | false | Output virtual oneof fields set to the present field's name |
--json | boolean | false | Represent Infinity and NaN as strings in float fields. Also decode google.protobuf.Any automatically |
--includeComments | boolean | false | Generate doc comments from comments in the original files |
-I, --includeDirs | array | - | Directories to search for included files |
-O, --outDir | string | required | Directory to output generated files |
--grpcLib | string | - | The gRPC implementation library (affects generated types) |
--inputTemplate | string | "%s" | Template for mapping input or "permissive" type names |
--outputTemplate | string | "%s__Output" | Template for mapping output or "restricted" type names |
--inputBranded | boolean | false | Output property for branded type for "permissive" types |
--outputBranded | boolean | false | Output property for branded type for "restricted" types |
--targetFileExtension | string | ".ts" | File extension for generated files |
--importFileExtension | string | "" | File extension for import specifiers in generated code |
# Generate basic TypeScript types
proto-loader-gen-types --outDir=./types proto/service.proto
# Multiple proto files
proto-loader-gen-types --outDir=./types proto/*.proto# Generate types compatible with @grpc/grpc-js
proto-loader-gen-types \
--longs=String \
--enums=String \
--defaults \
--oneofs \
--grpcLib=@grpc/grpc-js \
--outDir=./proto \
proto/*.proto# Generate with custom templates and comments
proto-loader-gen-types \
--longs=String \
--enums=String \
--defaults \
--oneofs \
--includeComments \
--inputTemplate="I%s" \
--outputTemplate="O%s" \
--grpcLib=@grpc/grpc-js \
-I ./proto \
-I ./external-proto \
--outDir=./generated \
proto/service.protoThe CLI tool generates several types of TypeScript definitions:
// Generated service interface
export interface MyServiceHandlers extends grpc.UntypedServiceImplementation {
myMethod: grpc.handleUnaryCall<MyRequest, MyResponse>;
myStreamMethod: grpc.handleServerStreamingCall<MyRequest, MyResponse>;
}
// Generated service definition
export const MyServiceService: grpc.ServiceDefinition<MyServiceHandlers>;// Input type (permissive, for creating messages)
export interface MyMessage {
field1?: string;
field2?: number;
optionalField?: string;
}
// Output type (with defaults applied, for receiving messages)
export interface MyMessage__Output {
field1: string;
field2: number;
optionalField: string;
}// Enum as const object
export const MyEnum = {
VALUE1: 'VALUE1',
VALUE2: 'VALUE2',
} as const;
// Enum type
export type MyEnum = 'VALUE1' | 'VALUE2';
export type MyEnum__Output = typeof MyEnum[keyof typeof MyEnum];// Complete package type combining all definitions
export interface ProtoGrpcType {
mypackage: {
MyService: SubtypeConstructor<typeof grpc.Client, MyServiceHandlers>;
MyMessage: MessageTypeDefinition;
MyEnum: EnumTypeDefinition;
};
}import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
import type { ProtoGrpcType } from './proto/service';
import type { MyServiceHandlers } from './proto/mypackage/MyService';
const packageDefinition = protoLoader.loadSync('./proto/service.proto');
const proto = (grpc.loadPackageDefinition(
packageDefinition
) as unknown) as ProtoGrpcType;
const server = new grpc.Server();
const serviceImplementation: MyServiceHandlers = {
myMethod: (call, callback) => {
// call.request is strongly typed
const response = { message: `Hello ${call.request.name}` };
callback(null, response);
},
};
server.addService(proto.mypackage.MyService.service, serviceImplementation);import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
import type { ProtoGrpcType } from './proto/service';
import type { MyServiceClient } from './proto/mypackage/MyService';
const packageDefinition = protoLoader.loadSync('./proto/service.proto');
const proto = (grpc.loadPackageDefinition(
packageDefinition
) as unknown) as ProtoGrpcType;
const client = new proto.mypackage.MyService(
'localhost:50051',
grpc.credentials.createInsecure()
) as MyServiceClient;
// Type-safe method calls
client.myMethod({ name: 'World' }, (error, response) => {
if (!error) {
// response is strongly typed
console.log(response.message);
}
});The CLI tool supports custom naming templates for generated types:
# Use I/O prefixes
proto-loader-gen-types \
--inputTemplate="I%s" \
--outputTemplate="O%s" \
--outDir=./types \
service.protoThis generates:
// Input types (permissive)
export interface IMyMessage {
field?: string;
}
// Output types (with defaults)
export interface OMyMessage {
field: string;
}# Generate branded types for additional type safety
proto-loader-gen-types \
--inputBranded \
--outputBranded \
--outDir=./types \
service.protoThe CLI tool provides detailed error messages for common issues:
Example Error Output:
Error: Proto file not found: ./proto/service.proto
at loadProtos (/path/to/proto-loader-gen-types.js:123:45)
Error: Parse error in service.proto:15:3
syntax error: expected ';' after field definition{
"scripts": {
"proto:gen": "proto-loader-gen-types --longs=String --enums=String --defaults --oneofs --grpcLib=@grpc/grpc-js --outDir=src/proto proto/*.proto",
"proto:watch": "chokidar 'proto/*.proto' -c 'npm run proto:gen'",
"prebuild": "npm run proto:gen"
}
}// webpack.config.js - Generate types before build
const { execSync } = require('child_process');
module.exports = {
// ... other config
plugins: [
{
apply: (compiler) => {
compiler.hooks.beforeCompile.tap('ProtoGen', () => {
execSync('npm run proto:gen', { stdio: 'inherit' });
});
}
}
]
};