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

Invalid/incomplete type inferred by generic components #9610

Open
pfumagalli opened this issue Nov 15, 2023 · 3 comments · May be fixed by #9652
Open

Invalid/incomplete type inferred by generic components #9610

pfumagalli opened this issue Nov 15, 2023 · 3 comments · May be fixed by #9652
Labels
has PR A pull request has already been submitted to solve the issue scope: types

Comments

@pfumagalli
Copy link

pfumagalli commented Nov 15, 2023

Vue version

3.3.8

Link to minimal reproduction

https://play.vuejs.org/#eNqlU8Fu2zAM/RVCl7ZAkADrLXM9ZG0P6aEp1qCXKBg8m/aUOpImyW0Dw/32UbLjOFjRDigQICb5SD4+UjWbaT1+qpBNWeRwq8vEYcwlQKQNxnUNN/eL27F1RshC5LvTnw6tG4GsynIEX86gaaKJR36UMjMm2b2ZF00Gfcm0qRHagUVXaSgTWVxw5ixnUKBEI1Iyl5yFhmKrlXHgdhqhhjuj9NJ/NpAbtYUTGuvElwRIlbQONAEsXECGuZDo4fa09mEAT3EKnUEmlZnC4tcGUweJ7UtHy3i0xxj8UwmD2RScqbBzN91/P/I/RYP3uOZq/V9Vm7N2mBIdBE1plDDS2Bs+MpnA6yvMZapIUHTYKiNkjoZK+qa5Kkv1bAnW4VeBHn0cGA6G/ToIHjPbR5o14ItDmVlY+cQodIOHUdsWruI1fINKPkr1LHvoA/nm+UzuIgLS7yqGKTk7sT7BZrjuw90dCRU8B7UuFWlDW/5YKtqTv9b2Pun+2IjuklrlohhvrJL0hAJ9zrz+okSz0E4QFc76K+As8VVvgm+wYcr5jenjG/6NffE+zu4MWjRPyFkfc4kp0LXh6/tbUncQ3KqsKgn9TvAHWlVWnmML+17JjGgPcIHtPDwzes1Le+0XaPdDeaLhMgOeM3pwl++MfqB7Pj4PeVw2rPkLt6l5Mg==

Steps to reproduce

I have a generic component, with a property mapping straight to the generic type:

<script setup lang="ts" generic="T">
  import type { PropType } from 'vue'

  const props = defineProps({
    test: {
      type: Object as PropType<T>,
      required: true,
      default: undefined,
    },
  })
</script>

The type inferred by props.test is not fully resolved, and instead of being T, it becomes the following:

[{
    type: PropType<T>;
    required: true;
}] extends [Prop<infer V, infer D>] ? unknown extends V ? IfAny<V, V, D> : V : {
    type: PropType<T>;
    required: true;
}

What is expected?

The type of the property should be resolved correctly to the generic type.

What is actually happening?

I narrowed this down to the InferPropType<T> type around here:

: [T] extends [Prop<infer V, infer D>]
? unknown extends V
? IfAny<V, V, D>
: V

Adding an extra condition to narrow inference even further makes the type work correctly:

type InferPropType<T> = [T] extends [null]
  ? any // null & true would fail to infer
  : [T] extends [{ type: null | true }]
  ? any // As TS issue https://github.com/Microsoft/TypeScript/issues/14829 // somehow `ObjectConstructor` when inferred from { (): T } becomes `any` // `BooleanConstructor` when inferred from PropConstructor(with PropMethod) becomes `Boolean`
  : [T] extends [ObjectConstructor | { type: ObjectConstructor }]
  ? Record<string, any>
  : [T] extends [BooleanConstructor | { type: BooleanConstructor }]
  ? boolean
  : [T] extends [DateConstructor | { type: DateConstructor }]
  ? Date
  : [T] extends [(infer U)[] | { type: (infer U)[] }]
  ? U extends DateConstructor
    ? Date | InferPropType<U>
    : InferPropType<U>
  // ~~~~~~~~ extra condition below, specific for `PropOptions`
  : [T] extends [PropOptions<infer V, infer D>]
  ? unknown extends D
    ? V 
    : V | D :
  // ~~~~~~~~
  : [T] extends [Prop<infer V, infer D>]
  ? unknown extends V
    ? IfAny<V, V, D>
    : V
  : T

System Info

No response

Any additional comments?

No response

@pfumagalli
Copy link
Author

@pfumagalli
Copy link
Author

A potential workaround is to use the (experimental) defineModel(...) macro. Typings for that are actually OK!

vuejs/rfcs#503

@pfumagalli
Copy link
Author

Proposed fix available in #9652

@pikax pikax added scope: types has PR A pull request has already been submitted to solve the issue labels Nov 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has PR A pull request has already been submitted to solve the issue scope: types
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants