WebReflection / uhtml

A micro HTML/SVG render

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Typescript issues

greentore opened this issue · comments

  1. render is typed to only allow () => uhtml.Hole when the documentation hints pasing holes directly is allowed too.
  2. html is typed to only allow primitive values or holes as values, which means inline event listeners like onclick=${handler} error.

what are you suggesting? I don't TS much so I might not fix this best

I took a closer look and realized 1 is a simple precedence error. Replacing () => Hole | Hole with (() => Hole) | Hole should fix it.
As for 2, I don't really understand the code well enough to suggest typings. The simplest solution would be to just use any / unknown in place of Value type (I believe that's how it was done in 3.x.x) to avoid false positives in user code.
Anyway, I managed to fix errors in my code by typing Value this way:

/**
 * @template T
 * @typedef {T | T[]} MaybeArray<T>
 */

/** @typedef {MaybeArray<null | undefined | string | number | boolean | Hole | ((...args: unknown[]) => unknown)>} Value */

but it's likely not bulletproof.

do you mind filing a PR? :D

Sure, I don't mind.
But first I want to know which approach you prefer: bailing out with unknown or trying to patch up Value type? Personally I'm leaning towards the former.

I don't care 🥳 I don't use TS and in this case it feels more like troubles than a feature, as the context is in the string surrounding the interpolation, and I am sure TS can't understand any of that, so it's OK to have any, actually that's probably for the best in general!

so, I went ahead and filed this MR #95

I think the function case is solved (even if for listeners is actually more like (event:Event) => void to me) but I am not sure what is the issue with Value ... it's currently specified as ...values:Value[] all over the place and it's never a maybe array of values, it's an always because of how tags work.

OK, I've published that MR so please let me know if anything is still problematic now or if it's "good enough" ... and feel free to re-open this if that's the case, thank you!

@WebReflection with current types it's not legal to return an array from an expression.

import { render, html } from 'uhtml';

render(document.querySelector('#todos'), html`
  <ul>
    ${databaseResults.map(value => html`<li>${value}</li>`)}
  </ul>
`);

For example this piece of code from the documentation is going to error because Hole[] isn't a valid Value. MaybeArray<T> utility type marks an array with elements of type T as valid too.

would Hole[] as extra type work? Maybe you are right that unknown is a better type ...

the thing is ... I think lists are accepted in two cases:

  • Hole[] as the only valid entry as Array within content
  • [listener, options] as the only valid entry as Array for listeners when @ prefix is used

how about a Value like this?

/**
 * @template T
 * @typedef {T | T[]} Value
 */

that solves most gotchas to me ... but maybe that's also unnecessary when this would do too?

/** @typedef {unknown | unknown[]} Value */

I might just go for the later kind, and eventually find a "bullet proof" solution in the future ... what do you think?

dho! ... unknown | unknown[] feels like an overengineered unknown ... I might just stick with unknown as Value for now and I will think further how to narrow down helping with types there.

let me know if unknown now works as expected or with less issues, thank you!

Yeah, it works correctly now. I will let you know if I find any other type issues.