Skip to content
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

Generated types allow assigning wrong message type if it is a superset of the target type #551

Open
LinearSpoon opened this issue Aug 15, 2023 · 0 comments

Comments

@LinearSpoon
Copy link

There is no compile error in const a: ProtoA = new ProtoB() if the fields in ProtoA are a subset of the fields in ProtoB.

example.proto

syntax = "proto3";

message Foo {
    int32 foo = 1;
}

message NotFoo {
    int32 foo = 2;  // Different tag number
}

// Foo with an extra field
message FooAndBar {
    int32 foo = 1;
    int32 bar = 2;  // Extra field
}

example.ts

import { Foo, FooAndBar, NotFoo } from "./example_pb.js";

// Unsafe - No compile time error
const a0: Foo = new FooAndBar();
const a1: Foo = new NotFoo();
const a2: NotFoo = new Foo();
const a3: NotFoo = new FooAndBar();

// Good - compile time error
const a4: FooAndBar = new Foo();  // Property 'bar' is missing in type 'Foo' but required in type 'FooAndBar'.
const a5: FooAndBar = new NotFoo();  // Property 'bar' is missing in type 'NotFoo' but required in type 'FooAndBar'.

// This also affects function parameters
function example(foo: Foo) { }
example(new NotFoo());  // Unsafe - No error

An example fix would be adding a dummy private variable to to every generated proto. TypeScript doesn't output any code when compiling this, so there should be no runtime implications (Playground Link).

Relevant TypeScript docs:

When an instance of a class is checked for compatibility, if the target type contains a private member, then the source type must also contain a private member that originated from the same class.

export class Foo extends Message<Foo> {
  private unused: any;

  // Existing generated code...
}

// Good - Compile time error
// Type 'FooAndBar' is not assignable to type 'Foo'.
//   Types have separate declarations of a private property 'unused'.
const a0: Foo = new FooAndBar();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant