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

Problem with defineProps and generic components #11487

Open
zumm opened this issue Aug 3, 2024 · 5 comments
Open

Problem with defineProps and generic components #11487

zumm opened this issue Aug 3, 2024 · 5 comments

Comments

@zumm
Copy link

zumm commented Aug 3, 2024

Vue version

3.4.35

Link to minimal reproduction

https://play.vuejs.org/#eNp9VNtu2zAM/RXOL2mBJMYuT4bToduKYRuwFVuwlzhAjJhJ3dqSIcm5IMu/j9TFcdAgfpLIQ+oc6siH6L5pxpsWoyRK9VKVjQGNpm2gysV6kkVGZ9FdJsq6kcrAVxSoyiWslKxhMI79nhsMMpGJpRTagGxMSQuYwOyQCQCR15jA4JcNw9vBkIObvGo5KgWXHodwAfruHGq2kqHzTKSx40rMaGOwbqrcIO0A0sAx8TRIhF9lkac2MrgzFOfTKBhTYRr3ukRD0k1aVuV6/KyloOFYdlm0lHVTVqgcQeqYON6cy6tKbr/bmFEtWuq25gmXLxfiz3rHsSx6VKhRbYhKlzO5WqNx6Yc/P4luL1nLoq0IfSX5G7WsWuboYJ9aURDtHs6y/WavtRTrqX7YGRQ6iGKijDxafBbRBX++Iv1E9/34g62je6Ip9vxxzWBcsXZQirimU+8BUoei0HCA2Q8oRYhPKQ7/wu4vO2SegDaKxHjWXQ+LDX08ZEJ2opAzWIe0fS5ArQMdlvmRRZzTGyUb9vm2NE9fcJW3ldE3jCpwVQp85HTqp+RNmMC9Uvk+9Sdaz4YkE/2Y9Gn3s5bcKW23dtZ3N7eW2tlBXM1vxoqEOAazb0iaUlK9ako4pxByfdbeFuIGBWgZ7HB7/fkV5cZrSt+MRr1TNd/ewk9hAbkows4etYDRKBRSD7eitz9aSdU9YW7RPeYASV5w3yFmvZbzgPF9aUJ+RPyRMiH7AzkNZWbvdXwaJP1yXP5IxrYU46AzrM5/IMf/aqjG3A==

Steps to reproduce

<script setup lang="ts"
  generic="
    TOption extends { [K in TOptionText | TOptionValue]: string },
    TOptionText extends string = 'text',
    TOptionValue extends string = 'value',
  "
>
const props = withDefaults(
  defineProps<{
    options: Array<TOption>
    optionText?: TOptionText
    optionValue?: TOptionValue
  }>(),
  {
    optionText: 'text', // type error
    optionValue: 'value' as TOptionValue, // even so
  },
)
</script>

<template>
  <div>
    <!-- type errors in `options` and `optionValue` -->
    <div
      v-for="option in options"
      :key="option[optionValue]"
    >
      {{
        // no error
        option[props.optionText]
      }}
    </div>
  </div>
</template>

What is expected?

Defining defaults and accessing props in template should be possible with generics.

What is actually happening?

This particular component works perfectly fine outside (see App.vue), but inside there is multiple problems.

At first, there is no way to specify defaults by withDefaults. Forcing type by as or redeclaring generic types like that TOptionText extends 'text' = 'text' can't help.

At second, accessing to props in template ends up with type errors. This is happening even without withDefaults.

System Info

No response

Any additional comments?

You can get rid of errors in template by using props.propName like access. But sometimes you can't.

@jh-leong
Copy link
Member

jh-leong commented Aug 3, 2024

In your case, the type errors you're encountering with withDefaults and generics in defineProps are expected behavior, see TS Playground

@zumm
Copy link
Author

zumm commented Aug 3, 2024

In your case, the type errors you're encountering with withDefaults and generics in defineProps are expected behavior, see TS Playground

I understand why typescript complains about this code, but i still can suppress error by casting type with as, see. I can't do the same with withDefaults.

offtop: but i don't understand why typescript complains about something like that too:

function bar<T extends 'text'>(text: T = 'text') {}

@jh-leong
Copy link
Member

jh-leong commented Aug 3, 2024

offtop: but i don't understand why typescript complains about something like that too:
function bar(text: T = 'text') {}

A simple counterexample is when T is never, which also satisfies the generic constraint. This results in the error "text"' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '"text"'.(2322).

You can get rid of errors in template by using props.propName like access. But sometimes you can't.

As a workaround, check out this playground. It seems that something unexpected happens when using option[optionValue]...

@zumm
Copy link
Author

zumm commented Aug 15, 2024

@k983551019 You should mark props as optional, withDefaults doesn't do it for you in case of generic for some reason. Don't know why tho.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants