5

I'm currently implementing some protocol buffers translation in my typescript project. I've gotten the proto files loaded into the ProtoBuilder (using the typescript definitions file from protobufjs.d.ts) and I've returned a ProtoBuf from the builder.

If I set a breakpoint after I have the ProtoBuf object in a variable named pb, I can call pb.decode(buffer) in the console and it works. TypeScript, however, doesn't like the syntax.

After much poking and prodding, including trying things like:

pb["decode"](buffer)

(This gives Error TS2349 Cannot invoke an expression whose type lacks a call signature.)

I still cannot get the TypeScript compiler like the code.

How do I get from a TypeScript ProtoBuf object to the decode function buried within the MetaMessage object?

If it matters, I'm in Visual Studio 2015 doing this.

edit: I can get around the problem using:

var decoder: any = pb["decode"];
decoder(buffer);

But I would prefer a more elegant solution if one exists.

Chris
  • 236
  • 3
  • 13
  • I know nothing about protobuf, but in TypeScript, you should be able to do `pb['decode'](buffer)`, or `(pb).decode(buffer)`. – Heretic Monkey May 02 '16 at 22:18
  • The first option (which apparently had the square braces removed in my question) was not effective, however, assigning var decoder: any = pb['decode']; did allow me a call to decoder(buffer). I'm hoping for a nicer looking answer, so I'll leave it open a bit, but I definitely appreciate the (pb) bit since that's likely to come in handy in the future. – Chris May 02 '16 at 22:34
  • "was not effective"? Did you get a build error? If so, adding that to your question would be quite helpful... – Heretic Monkey May 02 '16 at 22:37
  • Added the error info to the question. Thanks. – Chris May 02 '16 at 22:57
  • Have you tried `pb.decode(buffer)`? – Nitzan Tomer May 02 '16 at 23:29
  • Yeah, that was my first attempt. Works fine from the console when I'm at a breakpoint, but TypeScript's compiler will have none of it. – Chris May 02 '16 at 23:31
  • You could alter the .d.ts file, and just add that method to the declaration, or add it in your own .d.ts file. See http://stackoverflow.com/a/18114282/215552. – Heretic Monkey May 03 '16 at 13:50
  • It would likely have to be in my own .d.ts file since altering it in the provided one breaks other declarations. I may end up going that route if there's not a better way. – Chris May 03 '16 at 16:27
  • @MikeMcCaughan If you can post your first comment as an answer, I'll accept it. It's working, I was just hoping someone else was using this combo of protobuf and TypeScript and had worked out some way of using the object that didn't require overriding the type. – Chris May 16 '16 at 17:38

1 Answers1

2

Working with definition files for existing JavaScript libraries can be tricky, because JavaScript is very loosely defined, whereas TypeScript is quite well defined. Without modifying the existing .d.ts file, or writing your own, the options are limited. Theoretically, the following should work:

pb['decode'](buffer)

But you mentioned it did not. Your workaround of setting an intermediate variable works fine:

var decoder: any = pb["decode"];
decoder(buffer);

This code is similar to the other workaround, which is to just declare pb as any. The following code does this inline:

(<any>pb).decode(buffer);

This code is basically telling the TypeScript compiler to "just pretend pb is something that has a decode method, or whatever".

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122