I am writing a Node.js application that is using Google Protocol Buffers to communicate with a C# client.
I am using the official Google's JavaScript compiler with CommonJS style imports. I have recently added linting to my project with eslint and specifically the default "google" config. VS Code offers semantic checking (setting ID js/ts.implicitProjectConfig.checkJs
) which combined with JSDoc, that the google lint style enforces, works very well for introducing a little bit of type-safety into my application. Now the issue is that I can't get the VS Code semantic checking to work with Protocol Buffers generated JS code. The code runs fine so at least Node understands the protocol buffer code.
Here is a small example code, index.js , that's giving me trouble:
// Alteratively following works for JSDoc as well: /** @typedef { import('./bar').Bar } Bar */
const {Bar} = require('./bar');
// The typedef imports are not working:
// /** @typedef { import('./foo_pb').fooPackage } fooPackage */
// ^ Warns "Namespace ...foo_pb has no exported member fooPackage"
// /** @typedef { import('./foo_pb').Foo } Foo */
// ^ Warns "Namespace ...foo_pb has no exported member Foo"
const fooPackage = require('./foo_pb');
/**
* @param {Bar} bar
*/
function useBar(bar) {
bar.printHi();
}
// VS Code warns "Namespace <abspath>/foo_pb has no exported member 'Foo'."
/**
* @param {fooPackage.Foo} foo
*/
function useFoo(foo) {
console.log(foo);
}
useBar(new Bar());
// VS Code warns "Property 'Foo' does not exist on type 'typeof import("<abspath>/foo_pb")'."
useFoo(fooPackage.Foo.FOO_OK);
Here is the foo.proto file and it generated output foo_pb.js :
// foo.proto
syntax = "proto3";
package fooPackage;
enum Foo {
FOO_UNSPECIFIED = 0;
FOO_OK = 1;
}
// foo_pb.js
var jspb = require('google-protobuf');
var goog = jspb;
var global = Function('return this')();
goog.exportSymbol('proto.fooPackage.Foo', null, global);
/**
* @enum {number}
*/
proto.fooPackage.Foo = {
FOO_UNSPECIFIED: 0,
FOO_OK: 1
};
goog.object.extend(exports, proto.fooPackage);
Here is bar.js used in the index.js that works as I would expect with the semantic checking:
/** A Bar class */
class Bar {
/** Prints hi */
printHi() {
console.log('Hi');
}
}
module.exports = {
Bar,
};
Here is my, abridged, package.json :
{
"main": "index.js",
"scripts": {
"build": "protoc --proto_path=./ --js_out=import_style=commonjs,binary:./ foo.proto",
"lint": "node_modules/.bin/eslint ./"
},
"dependencies": {
"google-protobuf": "^3.14.0"
},
"devDependencies": {
"eslint": "^7.18.0",
"eslint-config-google": "^0.14.0"
}
}
It's not clear to me whether this is issue with VS Code, the Google's protocol buffer code or JSDoc and how does TypeScript and Closure play into this.
A reasonable solution for me to use following require syntax: const Foo = require('./foo_pb').Foo;
.
VS Code semantic checking does NOT complain about it, but it does have following downsides:
const fooPackage = require('./foo_pb');
imports all symbols into fooPackage
"namespace". This could be argued is actually a benefit since the whole "Include what you use" principle.no-unused-vars
on those imports if they are, for example, just function parameters. A simple solution for me is to wrap those imports /* eslint-disable no-unused-vars */
blocks.Just for reference, here is working index.js :
const {Bar} = require('./bar');
const Foo = require('./foo_pb').Foo;
/**
* @param {Bar} bar
*/
function useBar(bar) {
bar.printHi();
}
/**
* @param {Foo} foo
*/
function useFoo(foo) {
console.log(foo);
}
useBar(new Bar());
useFoo(Foo.FOO_OK);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.