I am trying to write a wrapper for web components which allows you to use them in JSX by referencing their key; implicitly this will also register the custom element if not done so already so that you don’t forget to.
Is it possible to have some abstract base class which defines a static method, and have children classes which extend this class, and have correct typing when accessing the method.
For example:
abstract class Base {
static _key: string
static get key() {
console.log(this._key)
return this._key
}
}
class Child extends Base {
static _key = "child" as const
}
// Want key to be of type "child", not string
const key = Child.key
If possible, I would prefer to do something like this (because this would allow me to type the props without having to modify IntrinsicElements
everywhere), but I’m noticing a similar problem
abstract class Base {
static _key: string
static Render(props: any) {
return "jsx-representation-of-element"
}
}
class Child extends Base {
static _key = "child" as const
}
// Some other file, test.tsx
// Expecting that the type is inferred to need Child's props, not Base's
const Component = <Child.Render />
I have been able to get around this by adding static key: typeof this._key
to Child
but this would require me adding it everywhere, so hoping I can find a solution which doesn’t require this.
For the first part, I looked into using this
as a parameter but this can’t be done on getters. I realise I could solve this by making it a normal method, and then calling it once outside the component function, referencing that variable inside the jsx tag, but that seems quite verbose.
I also tried making Base
take a generic parameter and returning this in Base.key
, ignoring the error about static members and generic types, but this just made the type T
(effectively any
)
For the second part, I was able to use the this
parameter, but as mentioned, the Child.Render
function thinks the this
type is Base
because it’s not been called yet.
Something like
abstract class Base {
static _key: string
static Render<T extends typeof Base>(this: T, props: Props<T>) {
return "jsx-representation-of-element"
}
}
Obviously, once I call Child.Render()
, the types are fine, but this won’t work if using inside a jsx tag.
Is there some tsconfig option I can use to make it default to Child
‘s this
?