From 23f26defa793b371c16b5f920fbacb3fb66bdf22 Mon Sep 17 00:00:00 2001 From: dcodeIO Date: Wed, 12 Apr 2017 15:33:54 +0200 Subject: [PATCH] Other: TypeScript generics improvements --- README.md | 18 ++++-- config/eslint.json | 3 +- index.d.ts | 146 +++++++++++++++++++++++++------------------ lib/inquire/index.js | 15 +++++ src/common.js | 2 - src/field.js | 4 +- src/mapfield.js | 4 +- src/message.js | 25 +++----- src/rpc.js | 2 +- src/rpc/service.js | 14 ++--- src/tokenize.js | 2 +- src/type.js | 7 +-- src/typescript.jsdoc | 26 ++------ src/util.js | 4 +- src/util/minimal.js | 12 ++-- src/wrappers.js | 13 ++-- 16 files changed, 158 insertions(+), 139 deletions(-) diff --git a/README.md b/README.md index 2afa91496..861d96f9e 100644 --- a/README.md +++ b/README.md @@ -543,7 +543,7 @@ export class AwesomeMessage extends Message { @Field.d(2, AwesomeSubMessage) public awesomeSubMessage: AwesomeSubMessage; - @Field.d(3, AwesomeEnum) + @Field.d(3, AwesomeEnum, "optional", AwesomeEnum.ONE) public awesomeEnum: AwesomeEnum; @OneOf.d("awesomeSubMessage", "awesomeEnum") @@ -551,26 +551,32 @@ export class AwesomeMessage extends Message { } -let message = new AwesomeMessage({ awesomeField: "hi" }); +// example code +let message = new AwesomeMessage({ awesomeField: "hello" }); let buffer = AwesomeMessage.encode(message).finish(); let decoded = AwesomeMessage.decode(buffer); ``` Supported decorators are: -* **Type.d(typeName?: `string`)**
- optionally annotates a class as a protobuf message type. If `typeName` is not specified, the constructor's runtime function name is used. +* **Type.d(typeName?: `string`)**   *(optional)*
+ annotates a class as a protobuf message type. If `typeName` is not specified, the constructor's runtime function name is used for the reflected type. * **Field.d<T>(fieldId: `number`, fieldType: `string | TMessageConstructor`, fieldRule?: `"optional" | "required" | "repeated"`, defaultValue?: `T`)**
annotates a property as a protobuf field with the specified id and protobuf type. -* **MapField.d<T extends { [key: string]: any }>(fieldId: `number`, fieldKeyType: `string`, fieldValueType. `string | TConstructor<{}>`)**
+* **MapField.d<T extends { [key: string]: any }>(fieldId: `number`, fieldKeyType: `string`, fieldValueType. `string | Constructor<{}>`)**
annotates a property as a protobuf map field with the specified id, protobuf key and value type. * **OneOf.d<T extends string>(...fieldNames: `string[]`)**
annotates a property as a protobuf oneof covering the specified fields. -Decorated types reside in `protobuf.roots["decorators"]` using a flat structure (no duplicate names). +Other notes: + +* Decorated types reside in `protobuf.roots["decorated"]` using a flat structure, so no duplicate names. +* Enums are copied to a reflected enum with a generic name on decorator evaluation because referenced enum objects have no runtime name the decorator could use. +* Default values must be specified as arguments to the decorator instead of using a property initializer for proper prototype behavior. +* Property names on decorated classes must not be renamed on compile time (i.e. by a minifier) because decorators just receive the original field name as a string. Command line ------------ diff --git a/config/eslint.json b/config/eslint.json index da9e09d83..d149c4d9a 100644 --- a/config/eslint.json +++ b/config/eslint.json @@ -97,9 +97,10 @@ "no-shadow-restricted-names": 1, "no-shadow": 0, // this is javascript. it has forEach and all that stuff. "no-undef-init": 1, - "no-undef": 1, + "no-undef": 2, "no-undefined": 0, // produces shorter code when testing against this "no-use-before-define": 0, // can actually be used for a better overview, i.e. with module.exports + "no-unused-vars": 1, // a warning is sufficient // Node.js and CommonJS "callback-return": 1, diff --git a/index.d.ts b/index.d.ts index 9fc966c13..6eb11eae6 100644 --- a/index.d.ts +++ b/index.d.ts @@ -193,22 +193,22 @@ export class Field extends FieldBase { * @param {"optional"|"required"|"repeated"} [fieldRule="optional"] Field rule * @param {T} [defaultValue] Default value * @returns {FieldDecorator} Decorator function - * @template T + * @template T extends number | number[] | Long | Long[] | string | string[] | boolean | boolean[] | Uint8Array | Uint8Array[] | Buffer | Buffer[] */ - public static d(fieldId: number, fieldType: ("double"|"float"|"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"string"|"bool"|"bytes"|object), fieldRule?: ("optional"|"required"|"repeated"), defaultValue?: T): FieldDecorator; + public static d(fieldId: number, fieldType: ("double"|"float"|"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"string"|"bool"|"bytes"|object), fieldRule?: ("optional"|"required"|"repeated"), defaultValue?: T): FieldDecorator; /** * Field decorator (TypeScript). * @name Field.d * @function * @param {number} fieldId Field id - * @param {TMessageConstructor} fieldType Field type + * @param {Constructor} fieldType Field type * @param {"optional"|"required"|"repeated"} [fieldRule="optional"] Field rule * @returns {FieldDecorator} Decorator function * @template T extends Message * @variation 2 */ - public static d>(fieldId: number, fieldType: TMessageConstructor, fieldRule?: ("optional"|"required"|"repeated")): FieldDecorator; + public static d>(fieldId: number, fieldType: Constructor, fieldRule?: ("optional"|"required"|"repeated")): FieldDecorator; } /** @@ -519,11 +519,11 @@ export class MapField extends FieldBase { * @function * @param {number} fieldId Field id * @param {"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"bool"|"string"} fieldKeyType Field key type - * @param {"double"|"float"|"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"bool"|"string"|"bytes"|Object|TConstructor<{}>} fieldValueType Field value type + * @param {"double"|"float"|"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"bool"|"string"|"bytes"|Object|Constructor<{}>} fieldValueType Field value type * @returns {FieldDecorator} Decorator function - * @template T extends { [key: string]: any } + * @template T extends { [key: string]: number | Long | string | boolean | Uint8Array | Buffer | number[] | Message<{}> } */ - public static d(fieldId: number, fieldKeyType: ("int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"bool"|"string"), fieldValueType: ("double"|"float"|"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"bool"|"string"|"bytes"|object|TConstructor<{}>)): FieldDecorator; + public static d }>(fieldId: number, fieldKeyType: ("int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"bool"|"string"), fieldValueType: ("double"|"float"|"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"bool"|"string"|"bytes"|object|Constructor<{}>)): FieldDecorator; } type MapFieldDescriptor = { @@ -541,25 +541,23 @@ type ExtensionMapFieldDescriptor = { options?: { [k: string]: any }; }; -type TMessageProperties = { [P in keyof T]?: T[P] }; - /** * Constructs a new message instance. * @classdesc Abstract runtime message. * @constructor - * @param {TMessageProperties} [properties] Properties to set - * @template T + * @param {Properties} [properties] Properties to set + * @template T extends object */ -export class Message { +export class Message { /** * Constructs a new message instance. * @classdesc Abstract runtime message. * @constructor - * @param {TMessageProperties} [properties] Properties to set - * @template T + * @param {Properties} [properties] Properties to set + * @template T extends object */ - constructor(properties?: TMessageProperties); + constructor(properties?: Properties); /** * Reference to the reflected type. @@ -582,9 +580,9 @@ export class Message { * @param {Object.} [properties] Properties to set * @returns {Message} Message instance * @template T extends Message - * @this TMessageConstructor + * @this Constructor */ - public static create>(this: TMessageConstructor, properties?: { [k: string]: any }): Message; + public static create>(this: Constructor, properties?: { [k: string]: any }): Message; /** * Encodes a message of this type. @@ -592,9 +590,9 @@ export class Message { * @param {Writer} [writer] Writer to use * @returns {Writer} Writer * @template T extends Message - * @this TMessageConstructor + * @this Constructor */ - public static encode>(this: TMessageConstructor, message: (T|{ [k: string]: any }), writer?: Writer): Writer; + public static encode>(this: Constructor, message: (T|{ [k: string]: any }), writer?: Writer): Writer; /** * Encodes a message of this type preceeded by its length as a varint. @@ -602,9 +600,9 @@ export class Message { * @param {Writer} [writer] Writer to use * @returns {Writer} Writer * @template T extends Message - * @this TMessageConstructor + * @this Constructor */ - public static encodeDelimited>(this: TMessageConstructor, message: (T|{ [k: string]: any }), writer?: Writer): Writer; + public static encodeDelimited>(this: Constructor, message: (T|{ [k: string]: any }), writer?: Writer): Writer; /** * Decodes a message of this type. @@ -613,9 +611,9 @@ export class Message { * @param {Reader|Uint8Array} reader Reader or buffer to decode * @returns {T} Decoded message * @template T extends Message - * @this TMessageConstructor + * @this Constructor */ - public static decode>(this: TMessageConstructor, reader: (Reader|Uint8Array)): T; + public static decode>(this: Constructor, reader: (Reader|Uint8Array)): T; /** * Decodes a message of this type preceeded by its length as a varint. @@ -624,9 +622,9 @@ export class Message { * @param {Reader|Uint8Array} reader Reader or buffer to decode * @returns {T} Decoded message * @template T extends Message - * @this TMessageConstructor + * @this Constructor */ - public static decodeDelimited>(this: TMessageConstructor, reader: (Reader|Uint8Array)): T; + public static decodeDelimited>(this: Constructor, reader: (Reader|Uint8Array)): T; /** * Verifies a message of this type. @@ -642,9 +640,9 @@ export class Message { * @param {Object.} object Plain object * @returns {T} Message instance * @template T extends Message - * @this TMessageConstructor + * @this Constructor */ - public static fromObject>(this: TMessageConstructor, object: { [k: string]: any }): T; + public static fromObject>(this: Constructor, object: { [k: string]: any }): T; /** * Creates a plain object from a message of this type. Also converts values to other types if specified. @@ -652,9 +650,9 @@ export class Message { * @param {ConversionOptions} [options] Conversion options * @returns {Object.} Plain object * @template T extends Message - * @this TMessageConstructor + * @this Constructor */ - public static toObject>(this: TMessageConstructor, message: T, options?: ConversionOptions): { [k: string]: any }; + public static toObject>(this: Constructor, message: T, options?: ConversionOptions): { [k: string]: any }; /** * Creates a plain object from this message. Also converts values to other types if specified. @@ -1496,9 +1494,9 @@ export let roots: { [k: string]: Root }; */ export namespace rpc { - type ServiceMethodCallback = (error: Error, response?: TRes) => void; + type ServiceMethodCallback> = (error: Error, response?: TRes) => void; - type ServiceMethod = (request: (TReq|TMessageProperties), callback?: rpc.ServiceMethodCallback) => Promise>; + type ServiceMethod, TRes extends Message> = (request: (TReq|Properties), callback?: rpc.ServiceMethodCallback) => Promise>; /** * Constructs a new RPC service instance. @@ -1545,15 +1543,15 @@ export namespace rpc { /** * Calls a service method through {@link rpc.Service#rpcImpl|rpcImpl}. * @param {Method|rpc.ServiceMethod} method Reflected or static method - * @param {TMessageConstructor} requestCtor Request constructor - * @param {TMessageConstructor} responseCtor Response constructor - * @param {TReq|TMessageProperties} request Request message or plain object + * @param {Constructor} requestCtor Request constructor + * @param {Constructor} responseCtor Response constructor + * @param {TReq|Properties} request Request message or plain object * @param {rpc.ServiceMethodCallback} callback Service callback * @returns {undefined} * @template TReq extends Message * @template TRes extends Message */ - public rpcCall, TRes extends Message>(method: (Method|rpc.ServiceMethod), requestCtor: TMessageConstructor, responseCtor: TMessageConstructor, request: (TReq|TMessageProperties), callback: rpc.ServiceMethodCallback): void; + public rpcCall, TRes extends Message>(method: (Method|rpc.ServiceMethod), requestCtor: Constructor, responseCtor: Constructor, request: (TReq|Properties), callback: rpc.ServiceMethodCallback): void; /** * Ends this service and emits the `end` event. @@ -1564,7 +1562,7 @@ export namespace rpc { } } -type RPCImpl = (method: (Method|rpc.ServiceMethod<{}, {}>), requestData: Uint8Array, callback: RPCImplCallback) => void; +type RPCImpl = (method: (Method|rpc.ServiceMethod, Message<{}>>), requestData: Uint8Array, callback: RPCImplCallback) => void; type RPCImplCallback = (error: Error, response?: Uint8Array) => void; @@ -1717,9 +1715,9 @@ export class Type extends NamespaceBase { * The registered constructor, if any registered, otherwise a generic constructor. * Assigning a function replaces the internal constructor. If the function does not extend {@link Message} yet, its prototype will be setup accordingly and static methods will be populated. If it already extends {@link Message}, it will just replace the internal constructor. * @name Type#ctor - * @type {TConstructor<{}>} + * @type {Constructor<{}>} */ - public ctor: TConstructor<{}>; + public ctor: Constructor<{}>; /** * Creates a message type from a message type descriptor. @@ -1771,9 +1769,8 @@ export class Type extends NamespaceBase { * Creates a new message of this type using the specified properties. * @param {Object.} [properties] Properties to set * @returns {Message<{}>} Message instance - * @template T */ - public create(properties?: { [k: string]: any }): Message<{}>; + public create(properties?: { [k: string]: any }): Message<{}>; /** * Sets up {@link Type#encode|encode}, {@link Type#decode|decode} and {@link Type#verify|verify}. @@ -1865,9 +1862,10 @@ type ConversionOptions = { arrays?: boolean; objects?: boolean; oneofs?: boolean; + json?: boolean; }; -type TypeDecorator> = (target: TMessageConstructor) => void; +type TypeDecorator> = (target: Constructor) => void; /** * Common type constants. @@ -2038,11 +2036,9 @@ export namespace types { }; } -type TConstructor = { new(...params: any[]): T }; - -type TMessageConstructor> = { new(properties?: TMessageProperties): T }; +type Constructor = { new(...params: any[]): T }; -type TObject = { [key: string]: V }; +type Properties = { [P in keyof T]?: T[P] } & { [key: string]: any }; type OneOfGetter = () => (string|undefined); @@ -2225,9 +2221,9 @@ export namespace util { /** * Node's Buffer class if available. - * @type {TConstructor} + * @type {Constructor} */ - let Buffer: TConstructor; + let Buffer: Constructor; /** * Creates a new buffer of whatever type supported by the environment. @@ -2238,15 +2234,15 @@ export namespace util { /** * Array implementation used in the browser. `Uint8Array` if supported, otherwise `Array`. - * @type {TConstructor} + * @type {Constructor} */ - let Array: TConstructor; + let Array: Constructor; /** * Long.js's Long class if available. - * @type {TConstructor} + * @type {Constructor} */ - let Long: TConstructor; + let Long: Constructor; /** * Regular expression used to verify 2 bit (`bool`) map keys. @@ -2305,19 +2301,19 @@ export namespace util { * Creates a custom error constructor. * @memberof util * @param {string} name Error name - * @returns {TConstructor} Custom error constructor + * @returns {Constructor} Custom error constructor */ - function newError(name: string): TConstructor; + function newError(name: string): Constructor; /** * Constructs a new protocol error. * @classdesc Error subclass indicating a protocol specifc error. * @memberof util * @extends Error - * @template T + * @template T extends Message * @constructor * @param {string} message Error message - * @param {Object.=} properties Additional properties + * @param {Object.} [properties] Additional properties * @example * try { * MyMessage.decode(someBuffer); // throws if required fields are missing @@ -2326,17 +2322,17 @@ export namespace util { * console.log("decoded so far: " + JSON.stringify(e.instance)); * } */ - class ProtocolError extends Error { + class ProtocolError> extends Error { /** * Constructs a new protocol error. * @classdesc Error subclass indicating a protocol specifc error. * @memberof util * @extends Error - * @template T + * @template T extends Message * @constructor * @param {string} message Error message - * @param {Object.=} properties Additional properties + * @param {Object.} [properties] Additional properties * @example * try { * MyMessage.decode(someBuffer); // throws if required fields are missing @@ -2370,8 +2366,20 @@ export namespace util { function oneOfSetter(fieldNames: string[]): OneOfSetter; /** - * Default conversion options used for {@link Message#toJSON} implementations. Longs, enums and bytes are converted to strings by default. + * Default conversion options used for {@link Message#toJSON} implementations. + * + * These options are close to proto3's JSON mapping with the exception that internal types like Any are handled just like messages. More precisely: + * + * - Longs become strings + * - Enums become string keys + * - Bytes become base64 encoded strings + * - (Sub-)Messages become plain objects + * - Maps become plain objects with all string keys + * - Repeated fields become arrays + * - NaN and Infinity for float and double fields become strings + * * @type {ConversionOptions} + * @see https://developers.google.com/protocol-buffers/docs/proto3?hl=en#json */ let toJSONOptions: ConversionOptions; @@ -2412,13 +2420,13 @@ export namespace util { /** * Decorator helper for types (TypeScript). - * @param {TMessageConstructor} ctor Constructor function + * @param {Constructor} ctor Constructor function * @param {string} [typeName] Type name, defaults to the constructor's name * @returns {Type} Reflected type * @template T extends Message * @property {Root} root Decorators root */ - function decorateType>(ctor: TMessageConstructor, typeName?: string): Type; + function decorateType>(ctor: Constructor, typeName?: string): Type; /** * Decorator helper for enums (TypeScript). @@ -2756,6 +2764,22 @@ export namespace util { */ export function verifier(mtype: Type): Codegen; +/** + * Wrappers for common types. + * @type {Object.} + * @const + */ +export const wrappers: { [k: string]: Wrapper }; + +type WrapperFromObjectConverter = (this: Type, object: { [k: string]: any }) => Message<{}>; + +type WrapperToObjectConverter = (this: Type, message: Message<{}>, options?: ConversionOptions) => { [k: string]: any }; + +type Wrapper = { + fromObject?: WrapperFromObjectConverter; + toObject?: WrapperToObjectConverter; +}; + /** * Constructs a new writer instance. * @classdesc Wire format writer using `Uint8Array` if available, otherwise `Array`. diff --git a/lib/inquire/index.js b/lib/inquire/index.js index 1a1f238a4..259011b17 100644 --- a/lib/inquire/index.js +++ b/lib/inquire/index.js @@ -15,3 +15,18 @@ function inquire(moduleName) { } catch (e) {} // eslint-disable-line no-empty return null; } + +/* +// maybe worth a shot to prevent renaming issues: +// see: https://github.com/webpack/webpack/blob/master/lib/dependencies/CommonJsRequireDependencyParserPlugin.js +// triggers on: +// - expression require.cache +// - expression require (???) +// - call require +// - call require:commonjs:item +// - call require:commonjs:context + +Object.defineProperty(Function.prototype, "__self", { get: function() { return this; } }); +var r = require.__self; +delete Function.prototype.__self; +*/ diff --git a/src/common.js b/src/common.js index 4bef2ef10..0a7f3ea6c 100644 --- a/src/common.js +++ b/src/common.js @@ -1,8 +1,6 @@ "use strict"; module.exports = common; -var Type = require("./type"); - /** * Provides common type definitions. * Can also be used to provide additional google types or your own custom types. diff --git a/src/field.js b/src/field.js index 4765b821a..1043988df 100644 --- a/src/field.js +++ b/src/field.js @@ -327,7 +327,7 @@ Field.prototype.resolve = function resolve() { * @param {"optional"|"required"|"repeated"} [fieldRule="optional"] Field rule * @param {T} [defaultValue] Default value * @returns {FieldDecorator} Decorator function - * @template T + * @template T extends number | number[] | Long | Long[] | string | string[] | boolean | boolean[] | Uint8Array | Uint8Array[] | Buffer | Buffer[] */ Field.d = function decorateField(fieldId, fieldType, fieldRule, defaultValue) { @@ -350,7 +350,7 @@ Field.d = function decorateField(fieldId, fieldType, fieldRule, defaultValue) { * @name Field.d * @function * @param {number} fieldId Field id - * @param {TMessageConstructor} fieldType Field type + * @param {Constructor} fieldType Field type * @param {"optional"|"required"|"repeated"} [fieldRule="optional"] Field rule * @returns {FieldDecorator} Decorator function * @template T extends Message diff --git a/src/mapfield.js b/src/mapfield.js index fd6a765b7..bfbab637a 100644 --- a/src/mapfield.js +++ b/src/mapfield.js @@ -108,9 +108,9 @@ MapField.prototype.resolve = function resolve() { * @function * @param {number} fieldId Field id * @param {"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"bool"|"string"} fieldKeyType Field key type - * @param {"double"|"float"|"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"bool"|"string"|"bytes"|Object|TConstructor<{}>} fieldValueType Field value type + * @param {"double"|"float"|"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"bool"|"string"|"bytes"|Object|Constructor<{}>} fieldValueType Field value type * @returns {FieldDecorator} Decorator function - * @template T extends { [key: string]: any } + * @template T extends { [key: string]: number | Long | string | boolean | Uint8Array | Buffer | number[] | Message<{}> } */ MapField.d = function decorateMapField(fieldId, fieldKeyType, fieldValueType) { diff --git a/src/message.js b/src/message.js index 9a3cb2e3b..82b800dd5 100644 --- a/src/message.js +++ b/src/message.js @@ -3,19 +3,12 @@ module.exports = Message; var util = require("./util"); -/** - * Properties of a message instance. - * @typedef TMessageProperties - * @template T - * @tstype { [P in keyof T]?: T[P] } - */ - /** * Constructs a new message instance. * @classdesc Abstract runtime message. * @constructor - * @param {TMessageProperties} [properties] Properties to set - * @template T + * @param {Properties} [properties] Properties to set + * @template T extends object */ function Message(properties) { // not used internally @@ -45,7 +38,7 @@ function Message(properties) { * @param {Object.} [properties] Properties to set * @returns {Message} Message instance * @template T extends Message - * @this TMessageConstructor + * @this Constructor */ Message.create = function create(properties) { return this.$type.create(properties); @@ -57,7 +50,7 @@ Message.create = function create(properties) { * @param {Writer} [writer] Writer to use * @returns {Writer} Writer * @template T extends Message - * @this TMessageConstructor + * @this Constructor */ Message.encode = function encode(message, writer) { return this.$type.encode(message, writer); @@ -69,7 +62,7 @@ Message.encode = function encode(message, writer) { * @param {Writer} [writer] Writer to use * @returns {Writer} Writer * @template T extends Message - * @this TMessageConstructor + * @this Constructor */ Message.encodeDelimited = function encodeDelimited(message, writer) { return this.$type.encodeDelimited(message, writer); @@ -82,7 +75,7 @@ Message.encodeDelimited = function encodeDelimited(message, writer) { * @param {Reader|Uint8Array} reader Reader or buffer to decode * @returns {T} Decoded message * @template T extends Message - * @this TMessageConstructor + * @this Constructor */ Message.decode = function decode(reader) { return this.$type.decode(reader); @@ -95,7 +88,7 @@ Message.decode = function decode(reader) { * @param {Reader|Uint8Array} reader Reader or buffer to decode * @returns {T} Decoded message * @template T extends Message - * @this TMessageConstructor + * @this Constructor */ Message.decodeDelimited = function decodeDelimited(reader) { return this.$type.decodeDelimited(reader); @@ -117,7 +110,7 @@ Message.verify = function verify(message) { * @param {Object.} object Plain object * @returns {T} Message instance * @template T extends Message - * @this TMessageConstructor + * @this Constructor */ Message.fromObject = function fromObject(object) { return this.$type.fromObject(object); @@ -129,7 +122,7 @@ Message.fromObject = function fromObject(object) { * @param {ConversionOptions} [options] Conversion options * @returns {Object.} Plain object * @template T extends Message - * @this TMessageConstructor + * @this Constructor */ Message.toObject = function toObject(message, options) { return this.$type.toObject(message, options); diff --git a/src/rpc.js b/src/rpc.js index 4ab2b27a9..f52c7ccab 100644 --- a/src/rpc.js +++ b/src/rpc.js @@ -10,7 +10,7 @@ var rpc = exports; * RPC implementation passed to {@link Service#create} performing a service request on network level, i.e. by utilizing http requests or websockets. * @typedef RPCImpl * @type {function} - * @param {Method|rpc.ServiceMethod<{},{}>} method Reflected or static method being called + * @param {Method|rpc.ServiceMethod,Message<{}>>} method Reflected or static method being called * @param {Uint8Array} requestData Request data * @param {RPCImplCallback} callback Callback function * @returns {undefined} diff --git a/src/rpc/service.js b/src/rpc/service.js index 59c699933..eb157a8f0 100644 --- a/src/rpc/service.js +++ b/src/rpc/service.js @@ -11,7 +11,7 @@ var util = require("../util/minimal"); * * Differs from {@link RPCImplCallback} in that it is an actual callback of a service method which may not return `response = null`. * @typedef rpc.ServiceMethodCallback - * @template TRes + * @template TRes extends Message * @type {function} * @param {?Error} error Error, if any * @param {?TRes} [response] Response message @@ -21,10 +21,10 @@ var util = require("../util/minimal"); /** * A service method part of a {@link rpc.Service} as created by {@link Service.create}. * @typedef rpc.ServiceMethod - * @template TReq - * @template TRes + * @template TReq extends Message + * @template TRes extends Message * @type {function} - * @param {TReq|TMessageProperties} request Request message or plain object + * @param {TReq|Properties} request Request message or plain object * @param {rpc.ServiceMethodCallback} [callback] Node-style callback called with the error, if any, and the response message * @returns {Promise>} Promise if `callback` has been omitted, otherwise `undefined` */ @@ -68,9 +68,9 @@ function Service(rpcImpl, requestDelimited, responseDelimited) { /** * Calls a service method through {@link rpc.Service#rpcImpl|rpcImpl}. * @param {Method|rpc.ServiceMethod} method Reflected or static method - * @param {TMessageConstructor} requestCtor Request constructor - * @param {TMessageConstructor} responseCtor Response constructor - * @param {TReq|TMessageProperties} request Request message or plain object + * @param {Constructor} requestCtor Request constructor + * @param {Constructor} responseCtor Response constructor + * @param {TReq|Properties} request Request message or plain object * @param {rpc.ServiceMethodCallback} callback Service callback * @returns {undefined} * @template TReq extends Message diff --git a/src/tokenize.js b/src/tokenize.js index 0168b8e2f..c49e6d289 100644 --- a/src/tokenize.js +++ b/src/tokenize.js @@ -246,7 +246,7 @@ function tokenize(source) { /** * Gets a comment. - * @param {number=} trailingLine Trailing line number if applicable + * @param {number} [trailingLine] Trailing line number if applicable * @returns {?string} Comment text * @inner */ diff --git a/src/type.js b/src/type.js index 78370cd8f..4e16904fa 100644 --- a/src/type.js +++ b/src/type.js @@ -84,7 +84,7 @@ function Type(name, options) { /** * Cached constructor. - * @type {TConstructor<{}>} + * @type {Constructor<{}>} * @private */ this._ctor = null; @@ -148,7 +148,7 @@ Object.defineProperties(Type.prototype, { * The registered constructor, if any registered, otherwise a generic constructor. * Assigning a function replaces the internal constructor. If the function does not extend {@link Message} yet, its prototype will be setup accordingly and static methods will be populated. If it already extends {@link Message}, it will just replace the internal constructor. * @name Type#ctor - * @type {TConstructor<{}>} + * @type {Constructor<{}>} */ ctor: { get: function() { @@ -416,7 +416,6 @@ Type.prototype.isReservedName = function isReservedName(name) { * Creates a new message of this type using the specified properties. * @param {Object.} [properties] Properties to set * @returns {Message<{}>} Message instance - * @template T */ Type.prototype.create = function create(properties) { return new this.ctor(properties); @@ -573,7 +572,7 @@ Type.prototype.toObject = function toObject(message, options) { * Decorator function as returned by {@link Type.d} (TypeScript). * @typedef TypeDecorator * @type {function} - * @param {TMessageConstructor} target Target constructor + * @param {Constructor} target Target constructor * @returns {undefined} * @template T extends Message */ diff --git a/src/typescript.jsdoc b/src/typescript.jsdoc index 9f6d72295..65e6a4b62 100644 --- a/src/typescript.jsdoc +++ b/src/typescript.jsdoc @@ -1,27 +1,13 @@ /** * Constructor type. - * @typedef TConstructor - * @template T + * @typedef Constructor + * @template T extends object * @tstype { new(...params: any[]): T } */ /** - * Properties of a message instance. - * @typedef TMessageProperties - * @template T extends Message - * @tstype { [P in keyof T]?: T[P] } - */ - -/** - * Message constructor type. - * @typedef TMessageConstructor - * @template T extends Message - * @tstype { new(properties?: TMessageProperties): T } - */ - -/** - * Object type. - * @typedef TObject - * @template V - * @tstype { [key: string]: V } + * Properties type. + * @typedef Properties + * @template T extends object + * @tstype { [P in keyof T]?: T[P] } & { [key: string]: any } */ diff --git a/src/util.js b/src/util.js index 33ad4176e..5e4ad2867 100644 --- a/src/util.js +++ b/src/util.js @@ -67,7 +67,7 @@ util.compareFieldsById = function compareFieldsById(a, b) { /** * Decorator helper for types (TypeScript). - * @param {TMessageConstructor} ctor Constructor function + * @param {Constructor} ctor Constructor function * @param {string} [typeName] Type name, defaults to the constructor's name * @returns {Type} Reflected type * @template T extends Message @@ -127,6 +127,6 @@ util.decorateEnum = function decorateEnum(object) { */ Object.defineProperty(util, "decorateRoot", { get: function() { - return roots["decorators"] || (roots["decorators"] = new (require("./root"))()); + return roots["decorated"] || (roots["decorated"] = new (require("./root"))()); } }); diff --git a/src/util/minimal.js b/src/util/minimal.js index 4992dbba6..5ca4ddf51 100644 --- a/src/util/minimal.js +++ b/src/util/minimal.js @@ -108,7 +108,7 @@ util.isSet = function isSet(obj, prop) { /** * Node's Buffer class if available. - * @type {TConstructor} + * @type {Constructor} */ util.Buffer = (function() { try { @@ -160,7 +160,7 @@ util.newBuffer = function newBuffer(sizeOrArray) { /** * Array implementation used in the browser. `Uint8Array` if supported, otherwise `Array`. - * @type {TConstructor} + * @type {Constructor} */ util.Array = typeof Uint8Array !== "undefined" ? Uint8Array /* istanbul ignore next */ : Array; @@ -176,7 +176,7 @@ util.Array = typeof Uint8Array !== "undefined" ? Uint8Array /* istanbul ignore n /** * Long.js's Long class if available. - * @type {TConstructor} + * @type {Constructor} */ util.Long = /* istanbul ignore next */ global.dcodeIO && /* istanbul ignore next */ global.dcodeIO.Long || util.inquire("long"); @@ -255,7 +255,7 @@ util.lcFirst = function lcFirst(str) { * Creates a custom error constructor. * @memberof util * @param {string} name Error name - * @returns {TConstructor} Custom error constructor + * @returns {Constructor} Custom error constructor */ function newError(name) { @@ -297,10 +297,10 @@ util.newError = newError; * @classdesc Error subclass indicating a protocol specifc error. * @memberof util * @extends Error - * @template T + * @template T extends Message * @constructor * @param {string} message Error message - * @param {Object.=} properties Additional properties + * @param {Object.} [properties] Additional properties * @example * try { * MyMessage.decode(someBuffer); // throws if required fields are missing diff --git a/src/wrappers.js b/src/wrappers.js index 2181f4b0e..8d09b8819 100644 --- a/src/wrappers.js +++ b/src/wrappers.js @@ -2,12 +2,12 @@ /** * Wrappers for common types. - * @namespace + * @type {Object.} + * @const */ var wrappers = exports; -var Message = require("./message"), - util = require("./util/minimal"); +var Message = require("./message"); /** * From object converter part of a {@link Wrapper}. @@ -23,7 +23,7 @@ var Message = require("./message"), * @typedef WrapperToObjectConverter * @type {function} * @param {Message<{}>} message Message instance - * @param {ConversionOptions=} options Conversion options + * @param {ConversionOptions} [options] Conversion options * @returns {Object.} * @this Type */ @@ -36,10 +36,7 @@ var Message = require("./message"), * @property {WrapperToObjectConverter} [toObject] To object converter */ -/** - * Custom wrapper for Any. - * @type {Wrapper} - */ +// Custom wrapper for Any wrappers[".google.protobuf.Any"] = { fromObject: function(object) {