error TS2345: Argument of type `'ISchoolService'` is not assignable to parameter of type `'ServiceDefinition<UntypedServiceImplementation>'`
I generate grpc Typescript code with:
"proto": "npx grpc_tools_node_protoc --js_out=import_style=commonjs,binary:./grpc/client --grpc_out=./grpc/client --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` -I ./grpc/proto ./grpc/proto/*.proto && npx grpc_tools_node_protoc --plugin=protoc-gen-ts=`which protoc-gen-ts` --ts_out=./grpc/client -I ./grpc/proto ./grpc/proto/*.proto",
and hit the following error:
Services/SchoolService.ts:205:23 - error TS2345: Argument of type 'ISchoolService' is not assignable to parameter of type 'ServiceDefinition<UntypedServiceImplementation>'.
Index signature for type 'string' is missing in type 'ISchoolService'.
205 server.addService(SchoolService, new ServerImpl());
Environment
- OS name, version and architecture: [e.g. Linux Ubuntu 18.04 amd64] Ubuntu 24.04
- Node version [e.g. 8.10.0] 22.4.1
- Node installation method [e.g. nvm]
apt - If applicable, compiler version [e.g. clang 3.8.0-2ubuntu4] g++ 13.2.0
- Package name and version [e.g. [email protected]]:
"grpc_tools_node_protoc_ts": "^5.3.3",
"@grpc/grpc-js": "^1.10.10",
What do I miss?
I got a similar error when I was building mine. I was able to resolve the issue by adding the following line to the service.ts file. I've attached my code for more clarity.
server.ts
import { Server, ServerCredentials } from '@grpc/grpc-js'
import { GreeterServiceService } from './proto/greet_grpc_pb'
import { GreeterService } from './service'
const main = () => {
const server = new Server()
server.bindAsync(
'0.0.0.0:50051',
ServerCredentials.createInsecure(),
(err: Error | null, port: number) => {
if (err) console.error('Error caught: ' + err)
server.addService(GreeterServiceService, new GreeterService())
console.log(`gRPC Server listening on port ${port}`)
},
)
}
main()
service.ts
import { handleUnaryCall, UntypedHandleCall } from '@grpc/grpc-js'
import { IGreeterServiceServer } from './proto/greet_grpc_pb'
import { GreetRequest, GreetResponse } from './proto/greet_pb'
export class GreeterService implements IGreeterServiceServer {
[name: string]: UntypedHandleCall \\ <---THE FIX IS HERE
greet: handleUnaryCall<GreetRequest, GreetResponse> = (call, callback) => {
const request = call.request
const response = new GreetResponse()
response.setResult(
'Hello, ' + request.getName() + '! Welcome to gRPC World :)',
)
callback(null, response)
}
}
I hope this helps!
Doesn't help.
Would you mind sharing the code?
https://github.com/khteh/Node.JSRestAPI
I can't find the file where the error occurred. Could you link it?
grpc branch. https://github.com/khteh/Node.JSRestAPI/blob/grpc/src/webapi/Services/SchoolService.ts
So I poked around and I think the compilation of your decorators might be part of the problem as an example this is my compiled file for my greeter service.
greet_grpc_pb.d.ts
// package: greeter
// file: greet.proto
/* tslint:disable */
/* eslint-disable */
import * as grpc from "@grpc/grpc-js";
import * as greet_pb from "./greet_pb";
interface IGreeterServiceService extends grpc.ServiceDefinition<grpc.UntypedServiceImplementation> {
greet: IGreeterServiceService_IGreet;
}
interface IGreeterServiceService_IGreet extends grpc.MethodDefinition<greet_pb.GreetRequest, greet_pb.GreetResponse> {
path: "/greeter.GreeterService/Greet";
requestStream: false;
responseStream: false;
requestSerialize: grpc.serialize<greet_pb.GreetRequest>;
requestDeserialize: grpc.deserialize<greet_pb.GreetRequest>;
responseSerialize: grpc.serialize<greet_pb.GreetResponse>;
responseDeserialize: grpc.deserialize<greet_pb.GreetResponse>;
}
export const GreeterServiceService: IGreeterServiceService;
// HERE
export interface IGreeterServiceServer extends grpc.UntypedServiceImplementation {
greet: grpc.handleUnaryCall<greet_pb.GreetRequest, greet_pb.GreetResponse>;
}
export interface IGreeterServiceClient {
greet(request: greet_pb.GreetRequest, callback: (error: grpc.ServiceError | null, response: greet_pb.GreetResponse) => void): grpc.ClientUnaryCall;
greet(request: greet_pb.GreetRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: greet_pb.GreetResponse) => void): grpc.ClientUnaryCall;
greet(request: greet_pb.GreetRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: greet_pb.GreetResponse) => void): grpc.ClientUnaryCall;
}
export class GreeterServiceClient extends grpc.Client implements IGreeterServiceClient {
constructor(address: string, credentials: grpc.ChannelCredentials, options?: Partial<grpc.ClientOptions>);
public greet(request: greet_pb.GreetRequest, callback: (error: grpc.ServiceError | null, response: greet_pb.GreetResponse) => void): grpc.ClientUnaryCall;
public greet(request: greet_pb.GreetRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: greet_pb.GreetResponse) => void): grpc.ClientUnaryCall;
public greet(request: greet_pb.GreetRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: greet_pb.GreetResponse) => void): grpc.ClientUnaryCall;
}
The interface that you have declare in the file is missing the inheritance of grpc.UntypedServiceImplementation
This is the commands I used to generate my files.
./scripts/gen.sh
npm install grpc_tools_node_protoc_ts --save-dev
# generate js codes via grpc-tools
grpc_tools_node_protoc \
--js_out=import_style=commonjs,binary:./proto \
--grpc_out=grpc_js:./proto \
--plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` \
-I ./proto \
./proto/*.proto
# generate d.ts codes
protoc \
--plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts \
--ts_out=grpc_js:./proto \
-I ./proto \
./proto/*.proto
Hopefully this helps :) Just an FYI I am just getting more familiar with writing TypeScript gRPC code.
Your build script seems to work but when I run the application:
$ n run start
> [email protected] start
> export NODE_ENV=development&& node build/src/webapi/server.js
file:///usr/src/Node.JSRestAPI/build/src/webapi/Services/SchoolService.js:10
import { CommonStudentsResponse } from "../grpc/client/school_pb.js";
^^^^^^^^^^^^^^^^^^^^^^
SyntaxError: The requested module '../grpc/client/school_pb.js' does not provide an export named 'CommonStudentsResponse'
at ModuleJob._instantiate (node:internal/modules/esm/module_job:171:21)
at async ModuleJob.run (node:internal/modules/esm/module_job:254:5)
at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:485:26)
at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:109:5)
Node.js v22.6.0
you need to use a package called ts-node