wonderful-panda/vue-tsx-support

Generics not working for component definitions when upgrading to version 3+

LolliDepp opened this issue · 3 comments

If I upgrade to version 3.2.0 from 2.3.3, generics stop working in my components

import * as tsx from 'vue-tsx-support';
import { Prop, Component } from 'vue-property-decorator';

interface IMyProps<TType> {
  items: TType[];
}

@Component
export default class AList<TType> extends tsx.Component<IMyProps<TType>> {
  // ...
}

With 2.3.3 I can use AList in other .tsx files and provide any kind of array for items and it will works

With 3.2.0 all my other components using AList are giving me error because TType of AList is inferred to be of type unknown instead

This code works with vue-tsx-support@3.2.0 (with TypeScript@3.9.2 or 4.3.5)
Can you show me a minimal reproduction ?

import { Component, Prop } from "vue-property-decorator";
import * as vuetsx from "vue-tsx-support";

interface ListProp<T> {
  items: T[];
}

@Component
class AList<T> extends vuetsx.Component<ListProp<T>> {
  @Prop()
  items!: T[];
}

const items: number[] = [1, 2, 3];
<AList items={items} />;

BTW, you can obtain typed component like below.

const ANumberList = AList as new () => AList<number>;

<ANumberList items={[1, 2, 3]} />;

Thank you for the answer - I'll see if I can followup with a minimal reproduction example.

Hello @wonderful-panda and @LolliDepp
I can confirm generic types are not correctly working. See the screenshot.

sandbox-vue-tsx-support

As you can see, items is (incorrectly) typed as (JSX attribute) items: (string | number)[], but it should be typed as number[] as we specify the generic type parameter number. The array [1, 2, 3, '2'] is accepted while it should not. This also leads to other errors when extending parent classes. I cannot provide the code to reproduce the error with the class, but the TypeScript server indicates :

The expected type comes from property 'items' which is declared here on type 'IntrinsicAttributes & (CombinedTsxComponentAttrs<{}, ListProp<string | number>, {}, {}, InnerScopedSlots<{}>, true> & {})'

sandbox-vue-tsx-support-2
Everything works as expected in v2.3.2.

Here is the code to reproduce (based on @wonderful-panda, but I think you did not check correctly the type, happens :)) :

/* eslint-disable max-classes-per-file */
import { Component, Prop } from 'vue-property-decorator';
import * as vuetsx from 'vue-tsx-support';

interface ListProp<T> {
  items: T[];
}

@Component
class AList<T extends number | string> extends vuetsx.Component<
  ListProp<T>,
  {}
> {
  @Prop()
  items!: T[];
}

@Component
class Test extends vuetsx.Component<{}> {
  render() {
    const items = [1, 2, 3, '2'];    
    // enable this to check TypeScript error
    // const items = [1, 2, 3, '2', new Date()];    
    return <AList<number> items={items} />;
  }
}

function test<T extends string | number>(items: T[]) {
  return false;
}

test<number>([1, 2, 'sd']);

Please do not hesitate to ask if you need more details.