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

Error TS2322 using Vue's dynamically named Slots #325

Closed
Shenor opened this issue May 12, 2022 · 9 comments
Closed

Error TS2322 using Vue's dynamically named Slots #325

Shenor opened this issue May 12, 2022 · 9 comments
Labels
kind: support Asking for support with something or a specific use case problem: removed issue template OP removed the issue template without good cause scope: integration Related to an integration, not necessarily to core (but could influence core) scope: vue Related to integration with Vue (rollup-plugin-vue is long archived), not core solution: out-of-scope This is out of scope for this project solution: Vue behavior This is Vue's behavior as well, so this is not a bug with this plugin solution: workaround available There is a workaround available for this issue

Comments

@Shenor
Copy link

Shenor commented May 12, 2022

What happens and why it is wrong

When assembling a project with dynamic slots, the following error appears:
image

[!] (plugin rpt2) Error: C:/Users/p.marusov/Desktop/element-ui/src/components/ElTable/ElTable.vue?vue&type=script&setup=true&lang.ts(227,7): semantic error TS2322: Type 'Function' is not assignable to type 'Slot'.
  Type 'Function' provides no match for the signature '(...args: any[]): VNode<RendererNode, RendererElement, { [key: string]: any; }>[]'.

The problem arises specifically because of this code. In its absence, the assembly is successful:

      <template v-for="(_, slot) in $slots" :key="_" #[slot]="scope">
        <slot :name="slot" v-bind="scope || {}" />
      </template>

rollup.config.js

:
export default [
  {
    input: "src/index.ts",
    output: [
      {
        format: "esm",
        file: "dist/index.mjs",
        exports: "named",
      },
      {
        format: "cjs",
        file: "dist/index.js",
        exports: "named",
      },
    ],
    external: ["vue", "quasar"],
    plugins: [
      del({ targets: "dist" }),
      peerDepsExternal(),
      nodeResolve(),
      vue(),
      typescript2({
        clean: true,
        typescript: ttypescript,
        tsconfig: "tsconfig.rollup.json",
      }),
      babel({ babelHelpers: "runtime" }),
      commonjs(),
      postcss(),
      image(),
      terser(),
    ],
  },
];

tsconfig.json

:
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "declaration": true,
    "removeComments": true,
    "moduleResolution": "node",
    "isolatedModules": true,
    "noImplicitAny": false,
    "sourceMap": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    },
    "plugins": [
      {
        "transform": "@zerollup/ts-transform-paths",
        "exclude": [
          "*"
        ]
      }
    ]
  },
  "files": [
    "src/index.ts",
    "src/shims-vue.d.ts"
  ],
  "exclude": ["node_modules"]
}

I tried to set the type of slots, but all to no avail.

 <template v-for="(_, slot) in ($slots as {})" :key="_" #[slot]="scope">
      <slot :name="slot" v-bind="scope || {}" />
    </template>

or

 <template v-for="(_, slot) in ($slots as Slots)" :key="_" #[slot]="scope">
      <slot :name="slot" v-bind="scope || {}" />
  </template>
<script lang="ts">
  import { Slots } from "vue";
</script>

I don't understand how this can be fixed.

@agilgur5 agilgur5 added the scope: integration Related to an integration, not necessarily to core (but could influence core) label May 12, 2022
@agilgur5 agilgur5 changed the title Error building with dynamically named slots vue Error TS2322 using Vue's dynamically named Slots May 13, 2022
@agilgur5
Copy link
Collaborator

agilgur5 commented May 15, 2022

I had to look up what Slots were as I'm not too familiar with Vue, seems like these are the equivalent of React's children props (except a good bit more complex, enough so that the docs have React JSX-like pseudo-code to explain it; thought Vue was supposed to be simpler and less Angular-y?)

Slots type coercion

$slots as {}
$slots as Slots

You can try $slots as any if you're trying to coerce the types, though I'm not sure if v-for even supports TS?

What does vue-tsc output?

It's possible the type-error is correct, what does vue-tsc output for this code?
This plugin just runs a TypeScript LanguageService on the resulting code, so generally it is supposed to have the same output as tsc as they both use the same TS API (+/- some Rollup semantics and config). This is a two-step compile though as it's a Vue SFC, so vue-tsc probably makes sense to check against.

It's quite difficult to tell what the issue is here given that this isn't raw TS (and hence not a minimal reproduction either) and it's using a handful of Vue-specific features at once on top of that.

Can also try check: false as a workaround

Another workaround you can do is to set check: false in this plugin's options to disable type-checking entirely and get the compilation to pass at least (and type-check with vue-tsc instead, for example).

@Shenor
Copy link
Author

Shenor commented May 16, 2022

vue-tsc did not give results. It doesn't output anything about dynamic slots. Disabling verification check: false is the only solution so far, but not the one that I would like. Thank you for the answer, I will continue to understand

@agilgur5 agilgur5 added the solution: workaround available There is a workaround available for this issue label May 16, 2022
@agilgur5
Copy link
Collaborator

agilgur5 commented Jul 7, 2022

@Shenor do you have a (minimal) reproduction of this issue?

I've been meticulously going through all the issues and doing root cause analyses and fixing most of them, but I can't really investigate this further without a reproduction.

@agilgur5 agilgur5 added problem: needs more info This issue needs more information in order to handle it problem: removed issue template OP removed the issue template without good cause problem: no repro No reproduction was provided (and have not tried to repro without one) labels Jul 7, 2022
@agilgur5
Copy link
Collaborator

@Shenor I created a minimal repro here and was unable to reproduce the error you received. rpt2 does not throw any error and neither does vue-tsc.

It's possible that there's something missing in my reproduction, but given the lack of details here, this is all I was able to come up with.

Without more input from you, there's nothing more that we can do here, and given the current inability to reproduce, it doesn't seem like this is an error within rpt2 either, but rather something in your environment, at least as far as I can tell given the current repro I created.

@agilgur5 agilgur5 added kind: support Asking for support with something or a specific use case solution: can't repro An attempt to reproduce has been tried and failed problem: stale Issue has not been responded to in some time labels Jul 23, 2022
@agilgur5
Copy link
Collaborator

agilgur5 commented Aug 2, 2022

Closing this as stale as OP has not responded in nearly a month and a reproduction has been unsuccessful.

Can re-open if a minimal repro is provided.

@agilgur5 agilgur5 closed this as completed Aug 2, 2022
@tiagoskaneta
Copy link

tiagoskaneta commented Oct 11, 2022

the issue I have is somewhat related. but it occurs when actually using a conditional template.
I forked @agilgur5 repo here.

in essence, by doing:

<my-component>
    <template v-if="true" #foo> Bar </template>
  </my-component>

This is being transpiled to:

function render(_ctx, _cache, $props, $setup, $data, $options) {
  const _component_my_component = resolveComponent("my-component");

  return (openBlock(), createBlock(_component_my_component, null, createSlots({ _: 2 /* DYNAMIC */ }, [
    {
          name: "foo",
          fn: withCtx(() => [
            _hoisted_1
          ])
        }
      
  ]), 1024 /* DYNAMIC_SLOTS */))
}

Where I get the following error:
image

Not really sure the issue is on rpt2 or on vue side, as it seems the transpiled/generated code doesn't match the interface of createSlots in this case.

For the record, I can get away with it by declaring something like this:

// types/vue.d.ts
import 'vue'
declare module 'vue' {
  function createSlots(
    slots: Record<string, any>,
    dynamicSlots: (any | any[] | undefined)[]
  ): Record<string, any>
}

Which is fine for my case as I never call the createSlots function directly, so the loss of proper type checking on it is okay.

@agilgur5
Copy link
Collaborator

@tiagoskaneta thanks for providing a detailed example and repro!

That definitely looks like a problem on the rollup-plugin-vue side, as it generates the render function (and not rpt2).

rollup-plugin-vue is no longer maintained though, so it's possible the typings are fixed in newer versions of the Vue compiler. Though I see the peerDep is just *, so it should use the same version of Vue as you have in your deps 🤔

So either there's some wrapper code that rollup-plugin-vue generates that's out-of-date, or this is still a bug in the Vue compiler's typings for SFCs

@agilgur5 agilgur5 added solution: Vue behavior This is Vue's behavior as well, so this is not a bug with this plugin solution: out-of-scope This is out of scope for this project and removed problem: needs more info This issue needs more information in order to handle it problem: stale Issue has not been responded to in some time solution: can't repro An attempt to reproduce has been tried and failed problem: no repro No reproduction was provided (and have not tried to repro without one) labels Nov 29, 2022
@d0peCode
Copy link

This issue still occure when I try to add v-if on my template:

<template #error v-if="errors.length">

With the newest version of Vue. It happens only when building for prod. typescript check doesn't see any issue

@michaelcozzolino
Copy link

michaelcozzolino commented Mar 13, 2023

This issue still occure when I try to add v-if on my template:

<template #error v-if="errors.length">

With the newest version of Vue. It happens only when building for prod. typescript check doesn't see any issue

hey, did you find a fix? it's happening to me too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: support Asking for support with something or a specific use case problem: removed issue template OP removed the issue template without good cause scope: integration Related to an integration, not necessarily to core (but could influence core) scope: vue Related to integration with Vue (rollup-plugin-vue is long archived), not core solution: out-of-scope This is out of scope for this project solution: Vue behavior This is Vue's behavior as well, so this is not a bug with this plugin solution: workaround available There is a workaround available for this issue
Projects
None yet
Development

No branches or pull requests

5 participants