-
Notifications
You must be signed in to change notification settings - Fork 5
Description
hey joe 👋
i have been playing around with lume/elements to make custom-element export for solid-shiki-textarea.
Issue
I noticed that the attributes of the custom-element were always string, while I defined the type with a more narrow type:
class ShikiTextareaElement extends Element {
@stringAttribute lang = 'tsx' as BundledLanguage
...
}I extended the namespace with ElementAttributes<ShikiTextareaElement, ...>:
declare module 'solid-js/jsx-runtime' {
namespace JSX {
interface IntrinsicElements {
'shiki-textarea': ElementAttributes<ShikiTextareaElement, 'cdn' | 'lang' | 'theme' | 'value'>
}
}
}Own exploration
I had a look inside ElementAttributes:
export type ElementAttributes<
ElementType,
SelectedProperties extends keyof ElementType,
AdditionalProperties extends object = {},
> = WithStringValues<DashCasedProps<Partial<Pick<ElementType, SelectedProperties>>>> &
AdditionalProperties &
Omit<JSX.HTMLAttributes<ElementType>, SelectedProperties | keyof AdditionalProperties>
type WithStringValues<Type extends object> = {
[Property in keyof Type]: Type[Property] extends string ? Type[Property] : Type[Property] | string
}And found that the culprit was Type[Property] extends string.
Type[Property] is in my setup typed as BundledLanguage | undefined which causes it to not fullfill the conditional. Type[Property] | string causes the type to be widened to string.
The fact that Type[Property] is typed as BundledLanguage | undefined and not BundledLanguage is due to my tsconfig setting: "noUncheckedIndexedAccess": true.
Patch
I was able to patch it to create the behavior that I wanted in the following way:
type WithStringValues<Type extends object> = {
[Property in keyof Type]: NonNullable<Type[Property]> extends string ? Type[Property] : Type[Property] | string
}where I wrapped Type[Property]> in a NonNullable to exclude undefined from its type.
I am not sure if this is the correct solution, that's why I preferred to write it up as an issue instead of a PR.