open-wc / custom-elements-manifest

Custom Elements Manifest is a file format that describes custom elements in your project.
https://custom-elements-manifest.open-wc.org/
225 stars 37 forks source link

custom elements manifest analyzer creates wrong types when using an interface #193

Closed beatgubler closed 1 year ago

beatgubler commented 1 year ago

Checklist

Expected behavior We are using the custom elements manifest analyzer to create a custom-elements.json that we can use in our storybook docs. We use lit with typescript decorators and types via an interface.

When we run our command it creates the types wrong:

{
  "kind": "field",
  "name": "text",
  "type": {
    "text": "IButton['text']"
  },
  "attribute": "text"
},

But it should create it like this:

{
  "kind": "field",
  "name": "text",
  "type": {
    "text": "string"
  },
  "attribute": "text"
},

Our interface:

export interface IButton {
    text: string;
}

Our WebComponent:

@property()
text: IButton['text'];

Our command: cem analyze --litelement --outdir "dist"

Is there a setting or config we can use, so that the types get correctly inferred from the interface? If it is a bug, will this be fixed soon?

Thanks!

andeeplus commented 1 year ago

Hi, I'm facing the same problem with the type assignment in lit element classes.

Here a minimal reproduction to see the problem in action:

https://stackblitz.com/edit/vitejs-vite-d2fdrz?file=src/my-element.ts

Looks like CEM cannot get the type reference correctly when collecting the manifest data. Does exist a plugin to collect the types definition from referenced types? Looks like no flags are available for this use case (https://custom-elements-manifest.open-wc.org/analyzer/config/). Am I missing something?

This is the custom-element-manifest.config.js

module.exports = {
  /** Globs to analyze */
  globs: ['src/**/*.ts'],
  /** Directory to output CEM to */
  outdir: '.',
  /** Output CEM path to `package.json`, defaults to true */
  packagejson: false,
  /** Enable special handling for litelement */
  litelement: true,
};

Ideally the following code:

export type Counter = number;

export type MyElementProps = {
  count: Counter;
  docsHint: string;
};

/**
 * An example element.
 *
 * @slot - This element has a slot
 * @csspart button - The button
 */
@customElement('my-element')
export class MyElement extends LitElement {
  /**
   * Copy for the read the docs hint.
   */
  @property()
  docsHint: MyElementProps['docsHint'] =
    'Click on the Vite and Lit logos to learn more';

  /**
   * The number of times the button has been clicked.
   */
  @property({ type: Number })
  count: MyElementProps['count'] = 0;

Should produce this:

// MyElement.ts
count: MyElementProps['count'] = 0;

// CEM Manifest
"members": [
            {
              "kind": "field",
              "name": "docsHint",
              "type": {
                "text": "string" // instead of  --> MyElementProps['docsHint']
              },
              "default": "'Click on the Vite and Lit logos to learn more'",
              "description": "Copy for the read the docs hint."
            },
            {
              "kind": "field",
              "name": "count",
              "type": {
                "text": "number" //  instead of  --> MyElementProps['count']
              },
              "default": "0",
              "description": "The number of times the button has been clicked."
            },

Thanks a lot

thepassle commented 1 year ago

The analyzer doesnt use typescripts typechecker because it makes analysis super slow. This means that it gives you the types in the manifest as is typed in the source code. You can override this behavior by using the overrideModuleCreation config function and implenting a custom plugin. You can find more info in the docs

andeeplus commented 1 year ago

Thanks for the quick response @thepassle. I'll play a bit with the hint you gave me and if I found the right way to do it I'll post the solution here for future reference.

thepassle commented 1 year ago

These are the docs I mentioned: https://custom-elements-manifest.open-wc.org/analyzer/plugins/authoring/#overriding-sourcefile-creation