Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic Component Declarations #149

Open
a11delavar opened this issue Nov 22, 2020 · 1 comment
Open

Generic Component Declarations #149

a11delavar opened this issue Nov 22, 2020 · 1 comment

Comments

@a11delavar
Copy link

a11delavar commented Nov 22, 2020

I was creating some custom elements from a generic base class using LitElement and came to some odd problems where the analyzer didn't type-check generic-related properties.

A simplified version of what I was doing:

export class GenericElement<T> extends LitElement {
	@property() key!: keyof T
}

declare global {
	interface HTMLElementTagNameMap {
		'generic-specific': GenericElement<{ id: number, name: string }>
	}
}

First I tried to do it the vanilla way and type checking works fine:

const element = document.createElement('generic-specific')
element.key = 'what' // ✅ TS2322: Type '"what"' is not assignable to type '"id" | "name"'.

However, for some reason, it doesn't work in tagged html templates:

export const someTemplate = () => html`
        <!-- ❌ Not type-checked -->
	<generic-specific key='what??'></generic-specific>
`

I guess the analyzer doesn't analyze the declared generic part in the HTMLElementTagNameMap? because it thinks the key is of type keyof T instead of keyof { id: number, name: string }.

Would be glad to know what I'm missing or to know if there are work-arounds for now. Also, if these generic declarations cannot be supported due to some TypeScript API limitations, would it make sense to disable these checks for now?

@mohe2015
Copy link

mohe2015 commented Jan 5, 2022

Anybody knows workarounds inside of html tagged templates that verify the type checks? The only one I could find is:

export function pwSelectInput<T, Q extends keyof T>(props: Pick<PwSelectInput<T, Q>, "onchange" | "disabled" | "initial" | "label" | "name" | "options" | "task">) {
  const {
    onchange,
    disabled,
    initial,
    label,
    name,
    options,
    task,
    ...rest
  } = props;
  const _: {} = rest;
  return html`<pw-select-input
    ?disabled=${disabled}
    @change=${onchange}
    label=${label}
    .name=${name}
    .options=${options}
    .task=${task}
    .initial=${initial}
  ></pw-select-input>`;
}

which I think is super ugly but it seems to work.

And how realistic is it that this gets implemented natively?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants