protocolbuffers / protobuf-javascript

BSD 3-Clause "New" or "Revised" License
375 stars 67 forks source link

Missing methods of Map type in npm package @types/google-protobuf #15

Closed renkei closed 2 years ago

renkei commented 3 years ago

What version of protobuf and what language are you using? Version: google-protobuf 3.17.3 and @types/google-protobuf 3.15.3 Language: JavaScript / Typescript

What did you do? Steps to reproduce the behavior:

  1. Use type map in a protobuf message
  2. Compile the proto file to JavaScript
  3. In a Typescript environment, try to access the map's value iterator that is part of the generated JavaScript code.

What did you expect to see Methods keys() and values() that return a key and a value iterator:

export class Map<K, V> {
  ...
  keys(): Map.Iterator<K>;
  values(): Map.Iterator<V>;
  ...
}

What did you see instead? In @types/google-protobufin file index.js I can find the key iterator only, the value iterator is missing:

export class Map<K, V> {
  constructor(
    arr: Array<[K, V]>,
    valueCtor?: {new(init: any): V});
  toArray(): Array<[K, V]>;
  toObject(includeInstance?: boolean): Array<[K, V]>;
  toObject<VO>(
    includeInstance: boolean,
    valueToObject: (includeInstance: boolean, valueWrapper: V) => VO): Array<[K, VO]>;
  static fromObject<TK, TV>(
    entries: Array<[TK, TV]>,
    valueCtor: any,
    valueFromObject: any): Map<TK, TV>;
  getLength(): number;
  clear(): void;
  del(key: K): boolean;
  getEntryList(): Array<[K, V]>;
  entries(): Map.Iterator<[K, V]>;
  keys(): Map.Iterator<K>;
  forEach(
    callback: (entry: V, key: K) => void,
    thisArg?: {}): void;
  set(key: K, value: V): this;
  get(key: K): (V | undefined);
  has(key: K): boolean;
}

export namespace Map {
  // This is implemented by jspb.Map.ArrayIteratorIterable_, but that class shouldn't be exported
  interface Iterator<T> {
    next(): IteratorResult<T>;
  }
  interface IteratorResult<T> {
    done: boolean;
    value: T;
  }
}

Anything else we should know about your project / environment As a workaround, you can cast to any first. Let's assume, you want to get an array of values from the map. Then

const myValueArray = Array.from(myMessage.getMymapfield().values())

will fail, because method values() is unknown to the Typescript compiler. But

const myValueArray = Array.from((myMessage.getMymapfield() as any).values())

will work, since the method values() is available in the generated Javascript code.

dibenede commented 2 years ago

It looks like this is a bug in the definitelytyped project that needs a small patch.

renkei commented 2 years ago

I've already solved this with my pull requests PR #54846 and PR #55084. Both were accepted and are part of @types/google-protobuf >= 3.15.5 now.