mtth / avsc

Avro for JavaScript :zap:
MIT License
1.27k stars 147 forks source link

Using seprately declared enum in union in record. #461

Open svirpridon opened 3 months ago

svirpridon commented 3 months ago

Hi,

I have a use case where I have an enum I want to declare outside the record. It works fine if I'm not using a union:

const enum = avro.Type.forSchema({
  name: "enum",
  type: "enum",
  symbols: ["foo", "bar", "baz"],
});

const record = avro.Type.forSchema({
  name: "record",
  type: "record",
  fields: [
    { name: "enum", type: enum },
  ],
});

But when I go to make it nullable with:

const record = avro.Type.forSchema({
  name: "record",
  type: "record",
  fields: [
    { name: "enum", type: ["null", enum], default: null },
  ],
});

I get a type error pointing to the enum in ["null", enum]:

error TS2322: Type 'Type' is not assignable to type 'DefinedType'.
  Type 'Type' is not assignable to type 'FixedType & LogicalTypeExtension'.
    Type 'Type' is missing the following properties from type 'FixedType': type, size

If I inline the union it works fine... but I don't want to do that. It'd work for one of my unions, but another one is a union of a couple thousand entries, and I need it in multiple places so that'd get unwieldy fast.

I also tried using the name of the enum as a named type in the record, but that doesn't seem to work.

Thanks for the useful library!

mtth commented 2 months ago

Hi @svirpridon. This is an issue with the typings, the underlying library supports this. Until this is fixed, it is safe to use an any cast here. Alternatively, you can use the name approach you mention by using the registry option:

const enumType = avro.Type.forSchema({
  name: "Enum",
  type: "enum",
  symbols: ["foo", "bar", "baz"],
});

const recordType = avro.Type.forSchema({
  name: "Record",
  type: "record",
  fields: [
    { name: "enum", type: ["null", "Enum"], default: null },
  ],
}, {registry: {Enum: enumType}});