Skip to content

Build breaks with certain property data types including generics and JSX.Element #350

Closed
@cjorasch

Description

@cjorasch

Stencil version:

I'm submitting a:

  • bug report

Current behavior:
The build breaks if you using certain property types in a component.

For example:

@Component({
    tag: 'formatted-list'
})
export class FormattedList<T = any> {

    // The list of values to be displayed
    @Prop() values: T[];

    // The function to transform a value to HTML
    @Prop() formatter?: ((value: T) => JSX.Element);

    // Delimiter between values
    @Prop() delim?: JSX.Element;

    render(): JSX.Element {
        const {values, formatter} = this;
        if (!values || !values.length) return null;
        const delim = this.delim || ', ';
        const result: JSX.Element[] = [];
        for (const value of values) {
            if (value != null) {
                if (result.length) result.push(delim);
                result.push(formatter ? formatter(value) : value.toString());
            }
        }
        return result;
    }
}

If you run nom start you get the following error:

[05:16.2]  @stencil/core v0.0.8-10
[05:16.2]  build, app, dev mode, started ...
[05:16.2]  compile started ...
[05:19.0]  compile finished in 2.85 s

[ ERROR ]  typescript: src/components.d.ts, line: 37
           Cannot find name 'T'.


[ ERROR ]  typescript: src/components.d.ts, line: 38
           Namespace 'global.JSX' has no exported member 'Element'.

These errors are related to the components.d.ts file where the attributes are defined:

  namespace JSXElements {
    export interface FormattedListAttributes extends HTMLAttributes {
      values?: T[];
      formatter?: ((value: T) => JSX.Element);
      delim?: JSX.Element;
    }
  }

Expected behavior:
It should be possible to use any valid TypeScript data types when creating components. This example is an attempt to create a simple reproducible case that illustrates the problems. I realize that it could be implemented differently to avoid the problems but the actual components I am working on are more involved.

The specific things I am trying to do in my components are:

  • Use generics to ensure that multiple related properties and methods have consistent data types. Changing from T[] to any[] would not be able to enforce the parameter type for the formatter function.
  • Use JSX.Element as a property value. This allows flexible values including strings or html. The error may also mean that other kinds of global types would also have problems.

Steps to reproduce:
The errors occur with version 0.0.8-10. When I revert to 0.0.8-8 the same errors exist in the components.d.ts file but at least I am able to start the application.

Potential approach:
One potential way to solve this problem would be to have the data type of the attributes reference the data type of the component class property by name. This is similar to how things like Partial<MyClass> work. For example:

  namespace JSXElements {
    export interface FormattedListAttributes extends HTMLAttributes {
        values?: FormattedList['values'],
        formatter?: FormattedList['formatter'],
        delim?: FormattedList['delim']
    }
  }

This would result in values: any[], etc.

It would not enforce type safety based on generics across attribute values, but the errors would go away.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions