TypeScript: Passing Attributes to Body Content Will Loose Type
sangxxh opened this issue · comments
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:
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>
@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;
}
@sangxxh the correct typing here would to use a
Marko.AttrTag
and aMarko.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" }]/>