vojtechhabarta / typescript-generator

Generates TypeScript from Java - JSON declarations, REST service client

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Incorrect tagged unions when using Jackson and nested subtypes

JoaoBrlt opened this issue · comments

Hi there,

First of all, I'd like to thank you for the amazing work behind this tool!
It's a fantastic tool that saves us a lot of time, while ensuring that types are respected on the client side.

Context

I'm currently using TypeScript Generator to generate TypeScript declarations for a large hierarchy of Java classes.
These classes have several levels of depth and are serialized/deserialized using Jackson.
I use the @JsonTypeInfo annotation on the root class and the @JsonSubTypes annotation at each depth level.
This way serialization/deserialization works and TypeScript Generator generates tagged unions which I need to properly type these classes. 👌

Actual behavior

The only issue is that classes referencing intermediate subtypes (classes referencing other subtypes) seem to generate incorrect tagged unions.
Indeed, tagged unions always seem to reference interface declarations and not the tagged unions of the subtypes (when they exist).

Expected behavior

I would expect the tagged unions to reference the tagged unions of the subtypes (when they exist).

Steps to reproduce

I created a small project to demonstrate the issue: typescript-generator-nested-subtypes.

The project is composed of the following classes:

The generated TypeScript declaration file is available here and looks like this:

export interface Animal {...}
export interface Mammal extends Animal {...}
export interface Bird extends Animal {...}
export interface Cat extends Mammal {...}
export interface Dog extends Mammal {...}
export interface Parrot extends Bird {...}
export interface Duck extends Bird {...}

export type AnimalUnion = Mammal | Bird;
export type MammalUnion = Cat | Dog;
export type BirdUnion = Parrot | Duck;

This means I cannot write something like this:

const animal: AnimalUnion = {
    type: "Cat",
    name: "Mittens",
    age: 3,
    numberOfLegs: 4,
    breed: "Tabby",
    favoriteMeal: "Tuna",
    children: [],
};

Indeed, this generates a TypeScript error:

Type '{ type: "Cat"; name: string; age: number; numberOfLegs: number; breed: string; favoriteMeal: string; children: never[]; }' is not assignable to type 'AnimalUnion'.
Object literal may only specify known properties, and 'breed' does not exist in type 'Mammal'.(2322)

For this reason, I would expected the generated tagged unions to look like this:

export type AnimalUnion = MammalUnion | BirdUnion;
export type MammalUnion = Cat | Dog;
export type BirdUnion = Parrot | Duck;

Don't hesitate to tell me if I missed something.

Cheers!