Skip to content

Commit 23f26de

Browse files
committed
Other: TypeScript generics improvements
1 parent e49bef8 commit 23f26de

File tree

16 files changed

+158
-139
lines changed

16 files changed

+158
-139
lines changed

README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -543,34 +543,40 @@ export class AwesomeMessage extends Message<AwesomeMessage> {
543543
@Field.d(2, AwesomeSubMessage)
544544
public awesomeSubMessage: AwesomeSubMessage;
545545

546-
@Field.d(3, AwesomeEnum)
546+
@Field.d(3, AwesomeEnum, "optional", AwesomeEnum.ONE)
547547
public awesomeEnum: AwesomeEnum;
548548

549549
@OneOf.d("awesomeSubMessage", "awesomeEnum")
550550
public which: string;
551551

552552
}
553553

554-
let message = new AwesomeMessage({ awesomeField: "hi" });
554+
// example code
555+
let message = new AwesomeMessage({ awesomeField: "hello" });
555556
let buffer = AwesomeMessage.encode(message).finish();
556557
let decoded = AwesomeMessage.decode(buffer);
557558
```
558559

559560
Supported decorators are:
560561

561-
* **Type.d(typeName?: `string`)**<br />
562-
optionally annotates a class as a protobuf message type. If `typeName` is not specified, the constructor's runtime function name is used.
562+
* **Type.d(typeName?: `string`)** &nbsp; *(optional)*<br />
563+
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.
563564

564565
* **Field.d&lt;T>(fieldId: `number`, fieldType: `string | TMessageConstructor<TField>`, fieldRule?: `"optional" | "required" | "repeated"`, defaultValue?: `T`)**<br />
565566
annotates a property as a protobuf field with the specified id and protobuf type.
566567

567-
* **MapField.d&lt;T extends { [key: string]: any }>(fieldId: `number`, fieldKeyType: `string`, fieldValueType. `string | TConstructor<{}>`)**<br />
568+
* **MapField.d&lt;T extends { [key: string]: any }>(fieldId: `number`, fieldKeyType: `string`, fieldValueType. `string | Constructor<{}>`)**<br />
568569
annotates a property as a protobuf map field with the specified id, protobuf key and value type.
569570

570571
* **OneOf.d&lt;T extends string>(...fieldNames: `string[]`)**<br />
571572
annotates a property as a protobuf oneof covering the specified fields.
572573

573-
Decorated types reside in `protobuf.roots["decorators"]` using a flat structure (no duplicate names).
574+
Other notes:
575+
576+
* Decorated types reside in `protobuf.roots["decorated"]` using a flat structure, so no duplicate names.
577+
* 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.
578+
* Default values must be specified as arguments to the decorator instead of using a property initializer for proper prototype behavior.
579+
* 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.
574580

575581
Command line
576582
------------

config/eslint.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@
9797
"no-shadow-restricted-names": 1,
9898
"no-shadow": 0, // this is javascript. it has forEach and all that stuff.
9999
"no-undef-init": 1,
100-
"no-undef": 1,
100+
"no-undef": 2,
101101
"no-undefined": 0, // produces shorter code when testing against this
102102
"no-use-before-define": 0, // can actually be used for a better overview, i.e. with module.exports
103+
"no-unused-vars": 1, // a warning is sufficient
103104

104105
// Node.js and CommonJS
105106
"callback-return": 1,

index.d.ts

Lines changed: 85 additions & 61 deletions
Large diffs are not rendered by default.

lib/inquire/index.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,18 @@ function inquire(moduleName) {
1515
} catch (e) {} // eslint-disable-line no-empty
1616
return null;
1717
}
18+
19+
/*
20+
// maybe worth a shot to prevent renaming issues:
21+
// see: https://github.com/webpack/webpack/blob/master/lib/dependencies/CommonJsRequireDependencyParserPlugin.js
22+
// triggers on:
23+
// - expression require.cache
24+
// - expression require (???)
25+
// - call require
26+
// - call require:commonjs:item
27+
// - call require:commonjs:context
28+
29+
Object.defineProperty(Function.prototype, "__self", { get: function() { return this; } });
30+
var r = require.__self;
31+
delete Function.prototype.__self;
32+
*/

src/common.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
"use strict";
22
module.exports = common;
33

4-
var Type = require("./type");
5-
64
/**
75
* Provides common type definitions.
86
* Can also be used to provide additional google types or your own custom types.

src/field.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ Field.prototype.resolve = function resolve() {
327327
* @param {"optional"|"required"|"repeated"} [fieldRule="optional"] Field rule
328328
* @param {T} [defaultValue] Default value
329329
* @returns {FieldDecorator} Decorator function
330-
* @template T
330+
* @template T extends number | number[] | Long | Long[] | string | string[] | boolean | boolean[] | Uint8Array | Uint8Array[] | Buffer | Buffer[]
331331
*/
332332
Field.d = function decorateField(fieldId, fieldType, fieldRule, defaultValue) {
333333

@@ -350,7 +350,7 @@ Field.d = function decorateField(fieldId, fieldType, fieldRule, defaultValue) {
350350
* @name Field.d
351351
* @function
352352
* @param {number} fieldId Field id
353-
* @param {TMessageConstructor<T>} fieldType Field type
353+
* @param {Constructor<T>} fieldType Field type
354354
* @param {"optional"|"required"|"repeated"} [fieldRule="optional"] Field rule
355355
* @returns {FieldDecorator} Decorator function
356356
* @template T extends Message<T>

src/mapfield.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@ MapField.prototype.resolve = function resolve() {
108108
* @function
109109
* @param {number} fieldId Field id
110110
* @param {"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"bool"|"string"} fieldKeyType Field key type
111-
* @param {"double"|"float"|"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"bool"|"string"|"bytes"|Object|TConstructor<{}>} fieldValueType Field value type
111+
* @param {"double"|"float"|"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"bool"|"string"|"bytes"|Object|Constructor<{}>} fieldValueType Field value type
112112
* @returns {FieldDecorator} Decorator function
113-
* @template T extends { [key: string]: any }
113+
* @template T extends { [key: string]: number | Long | string | boolean | Uint8Array | Buffer | number[] | Message<{}> }
114114
*/
115115
MapField.d = function decorateMapField(fieldId, fieldKeyType, fieldValueType) {
116116

src/message.js

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,12 @@ module.exports = Message;
33

44
var util = require("./util");
55

6-
/**
7-
* Properties of a message instance.
8-
* @typedef TMessageProperties
9-
* @template T
10-
* @tstype { [P in keyof T]?: T[P] }
11-
*/
12-
136
/**
147
* Constructs a new message instance.
158
* @classdesc Abstract runtime message.
169
* @constructor
17-
* @param {TMessageProperties<T>} [properties] Properties to set
18-
* @template T
10+
* @param {Properties<T>} [properties] Properties to set
11+
* @template T extends object
1912
*/
2013
function Message(properties) {
2114
// not used internally
@@ -45,7 +38,7 @@ function Message(properties) {
4538
* @param {Object.<string,*>} [properties] Properties to set
4639
* @returns {Message<T>} Message instance
4740
* @template T extends Message<T>
48-
* @this TMessageConstructor<T>
41+
* @this Constructor<T>
4942
*/
5043
Message.create = function create(properties) {
5144
return this.$type.create(properties);
@@ -57,7 +50,7 @@ Message.create = function create(properties) {
5750
* @param {Writer} [writer] Writer to use
5851
* @returns {Writer} Writer
5952
* @template T extends Message<T>
60-
* @this TMessageConstructor<T>
53+
* @this Constructor<T>
6154
*/
6255
Message.encode = function encode(message, writer) {
6356
return this.$type.encode(message, writer);
@@ -69,7 +62,7 @@ Message.encode = function encode(message, writer) {
6962
* @param {Writer} [writer] Writer to use
7063
* @returns {Writer} Writer
7164
* @template T extends Message<T>
72-
* @this TMessageConstructor<T>
65+
* @this Constructor<T>
7366
*/
7467
Message.encodeDelimited = function encodeDelimited(message, writer) {
7568
return this.$type.encodeDelimited(message, writer);
@@ -82,7 +75,7 @@ Message.encodeDelimited = function encodeDelimited(message, writer) {
8275
* @param {Reader|Uint8Array} reader Reader or buffer to decode
8376
* @returns {T} Decoded message
8477
* @template T extends Message<T>
85-
* @this TMessageConstructor<T>
78+
* @this Constructor<T>
8679
*/
8780
Message.decode = function decode(reader) {
8881
return this.$type.decode(reader);
@@ -95,7 +88,7 @@ Message.decode = function decode(reader) {
9588
* @param {Reader|Uint8Array} reader Reader or buffer to decode
9689
* @returns {T} Decoded message
9790
* @template T extends Message<T>
98-
* @this TMessageConstructor<T>
91+
* @this Constructor<T>
9992
*/
10093
Message.decodeDelimited = function decodeDelimited(reader) {
10194
return this.$type.decodeDelimited(reader);
@@ -117,7 +110,7 @@ Message.verify = function verify(message) {
117110
* @param {Object.<string,*>} object Plain object
118111
* @returns {T} Message instance
119112
* @template T extends Message<T>
120-
* @this TMessageConstructor<T>
113+
* @this Constructor<T>
121114
*/
122115
Message.fromObject = function fromObject(object) {
123116
return this.$type.fromObject(object);
@@ -129,7 +122,7 @@ Message.fromObject = function fromObject(object) {
129122
* @param {ConversionOptions} [options] Conversion options
130123
* @returns {Object.<string,*>} Plain object
131124
* @template T extends Message<T>
132-
* @this TMessageConstructor<T>
125+
* @this Constructor<T>
133126
*/
134127
Message.toObject = function toObject(message, options) {
135128
return this.$type.toObject(message, options);

src/rpc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ var rpc = exports;
1010
* RPC implementation passed to {@link Service#create} performing a service request on network level, i.e. by utilizing http requests or websockets.
1111
* @typedef RPCImpl
1212
* @type {function}
13-
* @param {Method|rpc.ServiceMethod<{},{}>} method Reflected or static method being called
13+
* @param {Method|rpc.ServiceMethod<Message<{}>,Message<{}>>} method Reflected or static method being called
1414
* @param {Uint8Array} requestData Request data
1515
* @param {RPCImplCallback} callback Callback function
1616
* @returns {undefined}

src/rpc/service.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ var util = require("../util/minimal");
1111
*
1212
* Differs from {@link RPCImplCallback} in that it is an actual callback of a service method which may not return `response = null`.
1313
* @typedef rpc.ServiceMethodCallback
14-
* @template TRes
14+
* @template TRes extends Message<TRes>
1515
* @type {function}
1616
* @param {?Error} error Error, if any
1717
* @param {?TRes} [response] Response message
@@ -21,10 +21,10 @@ var util = require("../util/minimal");
2121
/**
2222
* A service method part of a {@link rpc.Service} as created by {@link Service.create}.
2323
* @typedef rpc.ServiceMethod
24-
* @template TReq
25-
* @template TRes
24+
* @template TReq extends Message<TReq>
25+
* @template TRes extends Message<TRes>
2626
* @type {function}
27-
* @param {TReq|TMessageProperties<TReq>} request Request message or plain object
27+
* @param {TReq|Properties<TReq>} request Request message or plain object
2828
* @param {rpc.ServiceMethodCallback<TRes>} [callback] Node-style callback called with the error, if any, and the response message
2929
* @returns {Promise<Message<TRes>>} Promise if `callback` has been omitted, otherwise `undefined`
3030
*/
@@ -68,9 +68,9 @@ function Service(rpcImpl, requestDelimited, responseDelimited) {
6868
/**
6969
* Calls a service method through {@link rpc.Service#rpcImpl|rpcImpl}.
7070
* @param {Method|rpc.ServiceMethod<TReq,TRes>} method Reflected or static method
71-
* @param {TMessageConstructor<TReq>} requestCtor Request constructor
72-
* @param {TMessageConstructor<TRes>} responseCtor Response constructor
73-
* @param {TReq|TMessageProperties<TReq>} request Request message or plain object
71+
* @param {Constructor<TReq>} requestCtor Request constructor
72+
* @param {Constructor<TRes>} responseCtor Response constructor
73+
* @param {TReq|Properties<TReq>} request Request message or plain object
7474
* @param {rpc.ServiceMethodCallback<TRes>} callback Service callback
7575
* @returns {undefined}
7676
* @template TReq extends Message<TReq>

0 commit comments

Comments
 (0)