-
Notifications
You must be signed in to change notification settings - Fork 349
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Repeated fields can be undefined #225
Comments
The proto3 spec is pretty clear that, when deserializing repeated fields, the initial value is always an empty list: "The default value for repeated fields is empty (generally an empty list in the appropriate language)." https://developers.google.com/protocol-buffers/docs/proto3 I get that doesn't match what you personally are looking for, but that's why it is that way today. Right now the IIRC your use case is "take some JSON off the wire and just use it after ...like... A baby step PR to make repeated fields optional with the existing |
I liked your last suggestion and went for the baby step PR already: #227 |
Should be released as v1.70.0, thanks! |
Hey @stephenh, this change breaks current usage and introduces an unexpected behavior that doesn't comply with the proto3 defaults guide Repeated fields should always default to an empty array, not to I suggest reverting this change and introducing a new change with the following behavior:
Message Type1 {
repeated Type2 field1 = 1;
Type2 field2 = 2;
} With export interface Type1 {
field1: Type2[];
field2: Type2 | undefined;
} With export interface Type1 {
field1: Type2[] | undefined;
field2: Type2 | undefined;
} With export interface Type1 {
field1?: Type2[];
field2?: Type2;
} With export interface Type1 {
field1: Type2[];
field2?: Type2;
} |
Hey @mharsat , thanks for the report! I was worried about this, per discussion above, i.e. you're right, this is "not proto3" behavior. I was hoping that existing users of I'll revert and push out a new version. I like your description of |
Okay, I pushed v1.72.0 that reverts the change, and we can work on a redo. |
Message received and understood, I'll pick it up... 🙂 |
I implemented the |
The current way of handling repeated doesn't feel right. Adding a new repeated field to the schema, shouldn't require updates to the application code, as per Protobuf spec repeated fields are optional (if not provided, they resolve to an empty list). While with current Ideally, there should be at least an option to relax that, so repeated fields are not implemented as required |
@medikoo have you tried |
@stephenh yes, it relaxes this restriction, but it also relaxes restriction on primitive values which are not marked as optional. So it introduces another issue |
@medikoo hm, it sounds like you want "repeated fields per spec are optional" (so adding new repeated fields doesn't require updating app code), but you do want "non-optional primitive fields are required" (so adding new primitive fields does require updating app code), even though "primitive fields per proto3 spec are also optional / have default values". If I'm following, this seems inconsistent? Fwiw I think this issue was originally file before we had Happy to re-open/file a follow up issue if there's a good articulation for a new |
@stephenh I believe the correct understanding of spec is as follows: message Test {
// required primitive property
string lorem = 1;
// optional primitive property
optional string ipsum = 2;
// optional repeated primitive property (note that spec does not support "optional repeated" notation)
repeated string other = 3
} And while |
@medikoo the default ts-proto output is focused on reading values and not writing them. From the Default values section:
So if a reader does Granted, a wrinkle of ts-proto's "just POJO interfaces" approach is that we use the same types for readers vs. writers, and you're focused on "when writing / creating"; for that we have the If you're unhappy with using |
Yes, and the current situation is that it (1) ignores if optional primitive is not provided, (2) crashes if required primitive is not provided, and (3) (!) crashes if optional repeated primitive is not provided. If for above schema, I'll do |
@medikoo do you mean "crashes" as in "throws a runtime error" or "crashes" as in it's a typescript compile error? If you mean "typescript compile error", yes, that behavior is still expected because:
I.e. you're confusing "what is the best API for readers" (what the I.e. ts-proto does not leave With the default ts-proto output, you should use |
I was referring to JavaScript execution of TS compiled to JS. I do not see any reasonable explanation for being ok not to pass optional primitive, but not being ok to not pass optional repeated primitive. |
What happened to this issue in the end? Let me show you my case. // from grpc server
@GrpcMethod('UsersService')
findAll(request: GrpcUser.UserQuery): Observable<GrpcUser.UserPage> {
return from(this.userEntity.find()).pipe(
switchMap(users => {
console.log('GrpcMethod', users) // users are '[]'
return of({
users,
})
}),
)
} // from grpc client
findAll() {
return this.usersGrpcService.findAll({}).pipe(
switchMap(({ users }) => {
console.log('GraphQL', users) // users are 'undefined' !????
return of(users ?? [])
}),
)
} // compiled ts file
export interface UserPage {
users: User[]; // The return value cannot be undefined.
} # ts-proto option
TS_ARGS_SERVER=('lowerCaseServiceMethods=true'
'outputEncodeMethods=false'
'outputJsonMethods=false'
'outputClientImpl=false'
'snakeToCamel=true'
'returnObservable=true'
'useDate=true'
'env=node') An empty array ('[]') is searched in the db, and an empty array ('[]') is sent, but why does the client receive 'undefined'? |
@JeHwanYoo any luck here? im also getting undefined for empty arrays in client, dont get what the point of that is |
It appears that a repeated field like this one:
Simply gives this as output:
But, if you use the standard NodeJS
protobufjs
serialization without addingdefaults: true
a deserialized message won't actually contain adocuments
field.So it seems more appropriate to output:
Or even:
Of course, it's always possible to add an option to turn this on or off using a setting similar to
--ts_proto_opt=stringEnums=true
(which BTW does nicely fit the theenums: String
override on theprotobufjs
(de)serializer).I could help on a PR for this, but first wanted to check what the preferred solution could be.
The text was updated successfully, but these errors were encountered: