marko-js / marko

A declarative, HTML-based language that makes building web apps fun

Home Page:https://markojs.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TypeScript: Passing Attributes to Body Content Will Loose Type

sangxxh opened this issue · comments

commented

Marko Version:

5.26.4, 5.28.1

Details

I have this example file:

export interface Input {
  heading: Marko.Renderable;
  content: Marko.Renderable;
}

<body>
  <${input.heading} data="Marko"/> // <---------- HOVER OVER data
  <hr>
  <${input.content}/>
</body>

Hover over data will show "data": string which is good:

image

But in the usage, data is now of type any:

// +page.marko
    <layout>
      <@heading|{ data }|> // <--------- data is expected to be of type `string`
        <h1>Hello ${data}</h1>
      </@heading>
      <@content>
        <p>...</p>
      </@content>
    </layout>

image

@sangxxh the correct typing here would to use a Marko.AttrTag and a Marko.Body type with parameters, in this case:

export interface Input {
  heading: Marko.AttrTag<{
    renderBody: Marko.Body<[{ data: TYPE_OF_DATA }]>
  }>;
  content: Marko.Renderable;
}
commented

@sangxxh the correct typing here would to use a Marko.AttrTag and a Marko.Body type with parameters, in this case:

export interface Input {
  heading: Marko.AttrTag<{
    renderBody: Marko.Body<[{ data: TYPE_OF_DATA }]>
  }>;
  content: Marko.Renderable;
}

That will still raise TypeScript error on my end though:

export interface Input {
  heading: Marko.AttrTag<{
    renderBody: Marko.Body<
      [
        {
          data: string;
        }
      ]
    >;
  }>;
  content: Marko.Renderable;
}

<body>
  <${input.heading} data="Marko"/>
                                ^^^ 
                                Argument of type '{ data: string; }' is not assignable to parameter of type 'Directives & { value: [{ data: string; }]; }'.
                                Object literal may only specify known properties, and '"data"' does not exist in type 'Directives & { value: [{ data: string; }]; }'.
  <hr>
  <${input.content}/>
</body>

This will erase the TypeScript error but break the app because data is not assigned.

<body>
  <${input.heading} value=[{ data: "Marko" }]/>
  <hr>
  <${input.content}/>
</body>

@sangxxh the issue here is actually because of a change between Marko class api and tags api.

When providing tag parameters, the best thing to do is use the unambiguous syntax in each api. For class api it's this:

<${input.heading}({ data: "marko" })/>

In tags api its this:

<${input.heading}=[{ data: "marko" }]/>