Skip to content

Commit

Permalink
fix: ignore $type field in DeepPartial (#282)
Browse files Browse the repository at this point in the history
* fix: ignore $type field in DeepPartial

* fix

Co-authored-by: aikoven <dan.lytkin@gmail.com>
  • Loading branch information
aikoven and aikoven authored Apr 23, 2021
1 parent 7417229 commit 6c5087e
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 6 deletions.
Binary file modified integration/type-registry/bar/bar.bin
Binary file not shown.
2 changes: 1 addition & 1 deletion integration/type-registry/bar/bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export type DeepPartial<T> = T extends Builtin
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
? { [K in Exclude<keyof T, '$type'>]?: DeepPartial<T[K]> }
: Partial<T>;

// If you get a compile-error about 'Constructor<Long> and ... have no overlap',
Expand Down
Binary file modified integration/type-registry/foo.bin
Binary file not shown.
4 changes: 4 additions & 0 deletions integration/type-registry/foo.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ import "google/protobuf/timestamp.proto";
message Foo {
google.protobuf.Timestamp timestamp = 1;
}

message Foo2 {
google.protobuf.Timestamp timestamp = 1;
}
66 changes: 65 additions & 1 deletion integration/type-registry/foo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ export interface Foo {
timestamp: Date | undefined;
}

export interface Foo2 {
$type: 'foo.Foo2';
timestamp: Date | undefined;
}

const baseFoo: object = { $type: 'foo.Foo' };

export const Foo = {
Expand Down Expand Up @@ -70,6 +75,65 @@ export const Foo = {

messageTypeRegistry.set(Foo.$type, Foo);

const baseFoo2: object = { $type: 'foo.Foo2' };

export const Foo2 = {
$type: 'foo.Foo2' as const,

encode(message: Foo2, writer: Writer = Writer.create()): Writer {
if (message.timestamp !== undefined) {
Timestamp.encode(toTimestamp(message.timestamp), writer.uint32(10).fork()).ldelim();
}
return writer;
},

decode(input: Reader | Uint8Array, length?: number): Foo2 {
const reader = input instanceof Reader ? input : new Reader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseFoo2 } as Foo2;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.timestamp = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},

fromJSON(object: any): Foo2 {
const message = { ...baseFoo2 } as Foo2;
if (object.timestamp !== undefined && object.timestamp !== null) {
message.timestamp = fromJsonTimestamp(object.timestamp);
} else {
message.timestamp = undefined;
}
return message;
},

toJSON(message: Foo2): unknown {
const obj: any = {};
message.timestamp !== undefined && (obj.timestamp = message.timestamp.toISOString());
return obj;
},

fromPartial(object: DeepPartial<Foo2>): Foo2 {
const message = { ...baseFoo2 } as Foo2;
if (object.timestamp !== undefined && object.timestamp !== null) {
message.timestamp = object.timestamp;
} else {
message.timestamp = undefined;
}
return message;
},
};

messageTypeRegistry.set(Foo2.$type, Foo2);

type Builtin = Date | Function | Uint8Array | string | number | undefined;
export type DeepPartial<T> = T extends Builtin
? T
Expand All @@ -78,7 +142,7 @@ export type DeepPartial<T> = T extends Builtin
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
? { [K in Exclude<keyof T, '$type'>]?: DeepPartial<T[K]> }
: Partial<T>;

function toTimestamp(date: Date): Timestamp {
Expand Down
2 changes: 1 addition & 1 deletion integration/type-registry/google/protobuf/timestamp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ export type DeepPartial<T> = T extends Builtin
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
? { [K in Exclude<keyof T, '$type'>]?: DeepPartial<T[K]> }
: Partial<T>;

function longToNumber(long: Long): number {
Expand Down
18 changes: 17 additions & 1 deletion integration/type-registry/type-registry-test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Foo } from './foo';
import { Foo, Foo2 } from './foo';
import { Bar } from './bar/bar';
import { messageTypeRegistry } from './typeRegistry';

Expand All @@ -22,4 +22,20 @@ describe('type-registry', () => {
expect(messageTypeRegistry.get('foo.Foo')).toBe(Foo);
expect(messageTypeRegistry.get('foo.bar.Bar')).toBe(Bar);
});

it('should ignore $type field when creating from partial', () => {
const foo2 = Foo2.fromPartial({});
expect(foo2).toMatchInlineSnapshot(`
Object {
"$type": "foo.Foo2",
"timestamp": undefined,
}
`);
expect(Foo.fromPartial(foo2)).toMatchInlineSnapshot(`
Object {
"$type": "foo.Foo",
"timestamp": undefined,
}
`);
});
});
2 changes: 1 addition & 1 deletion integration/type-registry/typeRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ export type DeepPartial<T> = T extends Builtin
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
? { [K in Exclude<keyof T, '$type'>]?: DeepPartial<T[K]> }
: Partial<T>;
3 changes: 2 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ function makeDeepPartial(options: Options, longs: ReturnType<typeof makeLongUtil

const maybeExport = options.exportCommonSymbols ? 'export' : '';
const maybeLong = options.forceLong === LongOption.LONG ? code` | ${longs.Long}` : '';
const keys = options.outputTypeRegistry ? code`Exclude<keyof T, '$type'>` : code`keyof T`;

// Based on the type from ts-essentials
const DeepPartial = conditionalOutput(
Expand All @@ -391,7 +392,7 @@ function makeDeepPartial(options: Options, longs: ReturnType<typeof makeLongUtil
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>${oneofCase}
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
? { [K in ${keys}]?: DeepPartial<T[K]> }
: Partial<T>;
`
);
Expand Down

0 comments on commit 6c5087e

Please sign in to comment.