typespec1-9 Exercise 2: Protobuf for a Parcel Service ============================================================ parcel_bad.tsp: import "@typespec/protobuf"; using TypeSpec.Protobuf; @package({ name: "post.v1" }) namespace Post; enum Speed { standard: 1, express: 2 } model Parcel { @field(1) id: string; weightGrams: int32; @field(3) sent: plainDate; @field(4) speed: Speed; } model TrackRequest { @field(1) id: string; } @Protobuf.service interface Tracking { track(...TrackRequest): Parcel[]; } PREDICTION (from the chapter's list) weightGrams has no @field -> field-index sent: plainDate -> unsupported-field-type enum Speed starts at 1 -> unconvertible-enum track returns Parcel[] (a bare list) -> an error naming Array Four problems expected, in one run. First compile (ONE error, not four): node_modules/@typespec/compiler/lib/intrinsics.tsp:224:7 - error @typespec/protobuf/model-not-in-package: model Array is not in a namespace that uses the '@Protobuf.package' decorator > 224 | model Array {} | ^^^^^ ex/parcel_bad.tsp:20:46 - occurred while instantiating template > 20 | interface Tracking { track(...TrackRequest): Parcel[]; } | ^^^^^^^^ Found 1 error. The other three were hidden. After changing track to return a TrackResponse message that holds the list (parcel_bad2.tsp), the second compile gave: ex/parcel_bad2.tsp:12:3 - error @typespec/protobuf/field-index: field weightGrams does not have a field index, but one is required (try using the '@field' decorator) > 12 | weightGrams: int32; | ^^^^^^^^^^^ node_modules/@typespec/compiler/lib/intrinsics.tsp:102:8 - error @typespec/protobuf/unsupported-field-type: no known protobuf scalar for TypeSpec scalar type plainDate > 102 | scalar plainDate { | ^^^^^^^^^ ex/parcel_bad2.tsp:8:14 - error @typespec/protobuf/unconvertible-enum: the first variant of an enum must be set to zero to be used in a Protobuf message > 8 | enum Speed { standard: 1, express: 2 } | ^^^^^^^^ Found 3 errors. All four predictions were right, but I saw them in two runs. parcel.tsp (fixed: @field(2) on weightGrams; sent as a string, because protobuf has no date scalar in this emitter; Speed with unspecified = 0; a TrackResponse message): import "@typespec/protobuf"; using TypeSpec.Protobuf; @package({ name: "post.v1" }) namespace Post; enum Speed { unspecified: 0, standard: 1, express: 2 } model Parcel { @field(1) id: string; @field(2) weightGrams: int32; @field(3) sent: string; @field(4) speed: Speed; } model TrackRequest { @field(1) id: string; } model TrackResponse { @field(1) parcels: Parcel[]; } @Protobuf.service interface Tracking { track(...TrackRequest): TrackResponse; } The .proto produced: // Generated by Microsoft TypeSpec syntax = "proto3"; package post.v1; enum Speed { unspecified = 0; standard = 1; express = 2; } message Parcel { string id = 1; int32 weightGrams = 2; string sent = 3; Speed speed = 4; } message TrackRequest { string id = 1; } message TrackResponse { repeated Parcel parcels = 1; } service Tracking { rpc Track(TrackRequest) returns (TrackResponse); } protoc (grpcio-tools 1.84.0) on it: exit code 0, no output. CHOICES AND LIMITS Turning plainDate into a string loses the type. Protobuf does have a well-known Timestamp type; I did not try to use it from TypeSpec, so I cannot say whether the emitter supports it. I did not run a server or client. WHY THIS WORKS AS AN ANSWER --------------------------- It practises the loop of prediction, compile, fix one thing, recompile; and it records that an error list is only the first layer.