Skip to content

Instantly share code, notes, and snippets.

@okayurisotto
Created April 11, 2023 04:27
Show Gist options
  • Save okayurisotto/9c3b80393c07db6f774874c7752a5312 to your computer and use it in GitHub Desktop.
Save okayurisotto/9c3b80393c07db6f774874c7752a5312 to your computer and use it in GitHub Desktop.
`customElements.define()`に渡す`name`のtype checkをしたかった
type Spread<T extends string> = T extends `${infer L}${infer R}`
? [L, ...Spread<R>]
: [];
type UpperAlphabet = Spread<"ABCDEFGHIJKLMNOPQRSTUVWXYZ">[number];
type LowerAlphabet = Lowercase<UpperAlphabet>;
type SpreadCheck<T extends string, U extends string> =
T extends `${infer L}${infer R}`
? L extends U
? [L, ...SpreadCheck<R, U>]
: never
: [];
type Every<T extends string, U extends string> =
Spread<T> extends SpreadCheck<T, U>
? T
: never;
type CustomElementName<T extends string> = `${string}-${string}` & Every<T, LowerAlphabet | "-">;
const defineCustomElement = <T extends string>(
name: CustomElementName<T>,
options?: Parameters<typeof customElements.define>[2]
) => {
return (constructor: Parameters<typeof customElements.define>[1]) => {
customElements.define(name, constructor, options);
};
};
@defineCustomElement("Custom-Element-Demo!")
class Bad extends HTMLElement {}
// Argument of type 'string' is not assignable to parameter of type 'never'.
@defineCustomElement("custom-element-demo")
class Good extends HTMLElement {}
// :)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment