gcanti / io-ts

Runtime type system for IO decoding/encoding
https://gcanti.github.io/io-ts/
MIT License
6.68k stars 331 forks source link

io-ts recursion use issue #686

Open t-pyrope opened 1 year ago

t-pyrope commented 1 year ago

Hello! I'm trying to use t.recursion of the library to document a type, that has recursion. But I've got an error in IDE and can't understand it. Could I ask you for help?

The type in the documentation looks like this:

export interface BoxBase {
  id?: string;
  mode: DockMode;
  size?: number;
  children: (BoxBase | PanelBase)[];
}

I wrote this:

const PanelBaseV = t.intersection([
    t.type({
        tabs: t.array(TabBaseV),
    }),
    t.partial({
          // ...
    })
])

interface BoxBaseV {
    mode: t.TypeOf<typeof DockModeV>,
    children: Array<BoxBaseV | t.TypeOf<typeof PanelBaseV>>,
    id?: Id,
    size?: number,
}

const BoxBaseV: t.Type<BoxBaseV> = t.recursion('BoxBaseV', (self) =>
    t.intersection([
        t.type({
            mode: DockModeV,
            children: t.array(
                t.union([ self, PanelBaseV ])
            ),
        }),
        t.partial({
            id: IdV,
            size: t.number,
        })
    ])
)

Then I get an error in IDE:

Type 'LayoutBase' is not assignable to type '{ dockbox: BoxBaseV; } & { floatbox?: BoxBaseV | undefined; windowbox?: BoxBaseV | undefined; maxbox?: BoxBaseV | undefined; }'.
   Type 'LayoutBase' is not assignable to type '{ dockbox: BoxBaseV; }'.
     The types of 'dockbox.children' are incompatible between these types.
       Type '(BoxBase | PanelBase)[]' is not assignable to type '(BoxBaseV | ({ tabs: { id: string; }[]; } & { id?: string | undefined; size?: number | undefined; oldSize?: number | undefined; activeId?: string | undefined; alwaysOnTop?: boolean | undefined; ... 4 more ...; h?: number | undefined; }))[]'.
         Type 'BoxBase | PanelBase' is not assignable to type 'BoxBaseV | ({ tabs: { id: string; }[]; } & { id?: string | undefined; size?: number | undefined; oldSize?: number | undefined; activeId?: string | undefined; alwaysOnTop?: boolean | undefined; ... 4 more ...; h?: number | undefined; })'.
           Type 'BoxBase' is not assignable to type 'BoxBaseV | ({ tabs: { id: string; }[]; } & { id?: string | undefined; size?: number | undefined; oldSize?: number | undefined; activeId?: string | undefined; alwaysOnTop?: boolean | undefined; ... 4 more ...; h?: number | undefined; })'.
             Type 'BoxBase' is not assignable to type 'BoxBaseV'.
               Types of property 'children' are incompatible.
                 Type '(BoxBase | PanelBase)[]' is not assignable to type '(BoxBaseV | ({ tabs: { id: string; }[]; } & { id?: string | undefined; size?: number | undefined; oldSize?: number | undefined; activeId?: string | undefined; alwaysOnTop?: boolean | undefined; ... 4 more ...; h?: number | undefined; }))[]'.
                   Type 'BoxBase | PanelBase' is not assignable to type 'BoxBaseV | ({ tabs: { id: string; }[]; } & { id?: string | undefined; size?: number | undefined; oldSize?: number | undefined; activeId?: string | undefined; alwaysOnTop?: boolean | undefined; ... 4 more ...; h?: number | undefined; })'.
                     Type 'BoxBase' is not assignable to type 'BoxBaseV | ({ tabs: { id: string; }[]; } & { id?: string | undefined; size?: number | undefined; oldSize?: number | undefined; activeId?: string | undefined; alwaysOnTop?: boolean | undefined; ... 4 more ...; h?: number | undefined; })'.
photz commented 1 year ago

What is LayoutBase?

t-pyrope commented 1 year ago

@photz LayoutBase is:

interface LayoutBase {
  dockbox: BoxBase;
  floatbox?: BoxBase;
  windowbox?: BoxBase;
  maxbox?: BoxBase;
}

And LayoutBaseV (which is my re-definition using io-ts):

const LayoutBaseV = t.intersection([
    t.type({
        dockbox: BoxBaseV,
    }),
    t.partial({
        floatbox: BoxBaseV,
        windowbox: BoxBaseV,
        maxbox: BoxBaseV,
    }),
])
photz commented 1 year ago

Am I missing something or is LayoutBase not actually being used in the code you are showing us? Could you create a minimal self-contained runnable example? When posting an issue, the easier you make it for others to reproduce the problem, the more likely you are to be helped.

t-pyrope commented 1 year ago

Hi, I just tried again in my IDE and there are no warnings anymore for some reason, can I close the issue?