-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to use TypeScript with reflection-based protos? #1014
Comments
The following should give you correct type information, unless import { hello } from './bundle';
let root = require('./bundle.js');
let HelloMessage = root.hello.HelloMessage; If |
Thanks for your example. Unfortunately, it doesn't work at runtime.
Renaming the package to Hello does work. This isn't a very usable option for us though as we can't rename the packages on our existing protos. What did you mean specifically by "unwrap"? |
Basically just putting it into top level. As a workaround, this might work: let hello = <root.hello>root.lookup("hello");
hello.HelloMessage ... |
I finally had time to figure this out and of course it's really simple. This works: import { Hello } from './bundle';
let msg = Hello.HelloMessage.create({message: 'hi'}); I couldn't understand where the requirement for capitalization came from. For some reason I thought it was something in TS. Finally after diving into the code with a debugger, I found that it's some code during
@dcodeIO: Can you explain what these conflicts are? Is it just the member functions and properties like decode, encode, etc? In your comment on the other issue you said:
It seems to me that namespaces don't really need this restriction since they don't really have any methods or properties. What am I missing? |
The restriction comes from exposing those properties on the reflection objects directly for convenience.
Here's namespace, with properties such as toJSON, addJSON, get, getEnum, add, remove, define, resolveAll, lookup etc. |
I guess I was only thinking of the TS namespace, not the reflected JS Namespace. Even so, couldn't those names just be marked as reserved? I doubt many people will have a namespace of "getEnum" or most of those others, and it would be easy enough to throw an error if they did. |
Hmm, also extends |
OK, I was able to put pbjs into an infinte loop by having a namespace named |
Hi, any progresss on this? I'm trying to use pbts and a json-module but I always get errors when using google.protobuf.Any ("Cannot read property protobuf of 'undefined'"). If this should be working please point me to an example of how to use TypeScript definitions with a json-module (I need reflection to be working). Cheers, patrick |
For anyone looking for a workaround to this issue (i.e. you are trying to use nested proto packages that have names starting with lowercase letters), what I've done in my project for now is modify
to simply remove the if condition. Or you could modify exposeRe to include lowercase letters. Keep in mind this is a little "risky" for reasons mentioned in the comments above, but if you're reasonably confident your package names won't run into such conflicts, this should hopefully let you get by until whenever this gets addressed with a more robust solution. (Note: you'll probably want to create a shim to modify |
May be we need change the README and point this issue for user who use This usage is unmatched, be careful about it. $> pbjs -t json-module -w commonjs -o bundle.js file1.proto file2.proto
$> pbjs -t static-module file1.proto file2.proto | pbts -o bundle.d.ts - // awesome.proto
package awesomepackage;
syntax = "proto3";
message AwesomeMessage {
string awesome_field = 1; // becomes awesomeField
} import { AwesomeMessage } from "./bundle.js";
// example code
let message = AwesomeMessage.create({ awesomeField: "hello" });
let buffer = AwesomeMessage.encode(message).finish();
let decoded = AwesomeMessage.decode(buffer); This is my usage. pbjs -t json-module -w commonjs -o awesome.json.js awesome.proto && pbjs -t static-module awesome.proto | pbts -o awesome.json.d.ts - Becareful about package name, as @kellycampbell said // awesome.proto
package AwesomePackage;
syntax = "proto3";
message AwesomeMessage {
string awesome_field = 1; // becomes awesomeField
} import { AwesomePackage } from './awesome.json.js'
const { AwesomeMessage } = AwesomePackage
let message = AwesomeMessage.create({ awesomeField: "hello" })
let buffer = AwesomeMessage.encode(message).finish()
let decoded = AwesomeMessage.decode(buffer) How can U do if U have to use an lowercase proto package name?
You can write a wrap function for root import * as root from './awesome.json.js'
const rootWrap = fixLowercaseProtoPkgNames<typeof root>(root, ['awesomepackage'])
const { AwesomeMessage } = rootWrap.awesomepackage
function fixLowercaseProtoPkgNames<T> (root: T, pkgNames: string[]): T {
const temp: any = root
for (let name of pkgNames) {
if (!temp[name] && temp.nested && temp.nested[name]) {
temp[name] = temp.nested[name]
}
}
return temp as T
} You can just use type directly import * as protobuf from 'protobufjs'
import { ad_event } from './ad_event'
const curRoot = require('./ad_event') as protobuf.Root
type Action = typeof ad_event.example.Action
type StatusMessage = typeof ad_event.example.StatusMessage
const Action: Action = curRoot.lookupEnum('ad_event.example.Action').values as any
const StatusMessage: StatusMessage = curRoot.lookupType('ad_event.example.StatusMessage') as any
console.log(Action.ActionNull)
console.log(StatusMessage.create().toJSON()) Hope can give U some help. |
I mourn the time lost trying to track this down :-( protobufjs/protobuf.js#1014 We can't patch the minified file in dist without essentially duplicating it, so this change also switches from the external file to including the src file as part of the bundle.
protobuf.js version: 6.8.6
I haven't been able to figure out how to use TS with reflected protos based on the documentation in the README. It would be helpful to have a more complete example on the wiki or something.
proto file:
Commands used to generate ts types:
I've tried a bunch of different things, but nothing really works as far as having good type info in the editor and still works at runtime. Here's some of the things I've tried:
Any guidance or better examples would be greatly appreciated.
The text was updated successfully, but these errors were encountered: