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

feat: allow imports of reusable Enum types #6030

Open
3 tasks done
MatteoFeltrin opened this issue Oct 16, 2024 · 8 comments
Open
3 tasks done

feat: allow imports of reusable Enum types #6030

MatteoFeltrin opened this issue Oct 16, 2024 · 8 comments
Labels
Bug: Validated This PR or Issue is verified to be a bug within Stencil Help Wanted

Comments

@MatteoFeltrin
Copy link

MatteoFeltrin commented Oct 16, 2024

Prerequisites

Stencil Version

4.22

Current Behavior

Inside a component we have this code:

// ...
// omitted useless code
// ...

export interface ConfirmationService {
    confirm(): void;
}

@Component({
    tag: 'my-component',
    shadow: true,
})
export class MyComponent{
// ...
// omitted useless code
// ...

Everything is compiling and working correctly.
This works only with interface, exporting Classes or Functions throws an error.
Is this fine and we can do that, or it may lead to unexpected behaviour and problems with the bundling as documented?

Expected Behavior

As documented here https://stenciljs.com/docs/module-bundling#one-component-per-module I would expect the compiler to throw something like:

[ ERROR ]  src/components/my-component.tsx:4:1
        To allow efficient bundling, modules using @Component() can only have a single export which is the component
        class itself. Any other exports should be moved to a separate file. For further information check out:
        https://stenciljs.com/docs/module-bundling

  L4:  export interface ConfirmationService()

System Info

No response

Steps to Reproduce

Export an interface from a component entry point.

Code Reproduction URL

none

Additional Information

No response

@ionitron-bot ionitron-bot bot added the triage label Oct 16, 2024
@christian-bromann
Copy link
Member

Is this fine and we can do that, or it may lead to unexpected behaviour and problems with the bundling as documented?

Hey @MatteoFeltrin 👋 thanks for raising the issue. Exporting interfaces is totally fine as these are being scrapped from the bundled files and only will be seen in the .d.ts files.

Let me know if you have any further questions.

@christian-bromann christian-bromann closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2024
@MatteoFeltrin
Copy link
Author

@christian-bromann Thanks for clarifying!

I was thinking to open a pull request to update the documentation. Do you think it is worth it?

Another doubt I have is:
Is not possibile to assign a type to a @prop which is imported from a non-component file?

import MyEnum from "../../../common/MyEnum ";
// ....
@Component({tag: 'my-component'})
export class MyComponent{
    @Prop() inputType!: MyEnum;
// ....

MyEnum .ts

enum MyEnum {
  First= '1',
  Second = '2',
}

export default MyEnum ;

The import from MyEnum is missing inside components.d.ts after compiling and the compiler is throwing this error:

  TypeScript: src/components.d.ts:18:22
           Cannot find name 'MyEnum'.

I found this issue that is close to this problem:
#3124

rwaskiewicz has updated the documentation here ionic-team/stencil-site#784 but is not clearly specified whether the "exported type" MUST be inside a component file or not.

Anyway Enums are those which cannot be exported inside a Component file, so it would not be possible to use it.

@christian-bromann
Copy link
Member

Yeah .. Enums are not just a type, they represent an actual object in JavaScript which causes this limitation. I am honestly not too familiar with this optimization in Stencil and have experienced the same in the past. At this point, if you think we can improve the docs for this, I would appreciate any contribution to our docs page.

@MatteoFeltrin
Copy link
Author

Ok, I will do that!

Do you have any advice on how I can assign to @prop a type that needs to be imported from "common" files that are not components?

My use case:
I have many "base" components that uses md-outlined-text-field, a component from MaterialDesign/web, and I would like to use a "common" Enum with all the possible "type" values of this TextField

// (from MaterialDesign documentation)
type="text"
type="email"
type="number"
type="password"
type="search"
type="tel"
type="url"
type="textarea"

@christian-bromann christian-bromann changed the title bug(question?): multiple "export" inside component file seems to be allowed feat: allow imports of reusable Enum types Oct 16, 2024
@christian-bromann
Copy link
Member

This sounds like a valid issue that should work or if not should be supported. I've renamed the issue and will re-open.

@christian-bromann christian-bromann added Bug: Validated This PR or Issue is verified to be a bug within Stencil Help Wanted and removed triage labels Oct 16, 2024
@MatteoFeltrin
Copy link
Author

@christian-bromann 🚀

Let me know if there is anything I can do to help with the issue

@christian-bromann
Copy link
Member

Let me know if there is anything I can do to help with the issue

Feel free to dive into it. I can't say when/if the Stencil team has time to take a look.

@MatteoFeltrin
Copy link
Author

@christian-bromann I have dived into it and found out that only NamedImports are considered by the components.d.ts generator.
If you use a DefaultImport it is considered as a global variable.

I explain it better with an example:
MyEnum.ts

enum MyEnum {
  Case1= '1',
  Case2= '2',
}
export default MyEnum;

component

import MyEnum from "../MyEnum ";
// ....
@Component({tag: 'my-component'})
export class MyComponent{
    @Prop() inputType!: MyEnum;
// ....

Inside the generated components.d.ts you will find this:
image
The import statement of MyEnum is missing beucase getTypeReferenceLocation considers it as a Global.

If on the other hand you use Named exports like this
MyEnum.ts

export enum MyEnum {
  Case1= '1',
  Case2= '2',
}

component

import { MyEnum } from "../MyEnum ";
// ....
@Component({tag: 'my-component'})
export class MyComponent{
    @Prop() inputType!: MyEnum;
// ....

Everything works fine and inside components.d.ts you will have:
image

I was trying to fix it but it is not an easy one, and what gives me many doubts is that it seems to be developed only for NamedImports on purpose.
May I ask you if Stencil team can confirm me that this fix really need to be done, or if there is any reason why they didn't support Default exports?
Just to avoid making a hard work for nothing!

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug: Validated This PR or Issue is verified to be a bug within Stencil Help Wanted
Projects
None yet
Development

No branches or pull requests

2 participants