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

Default export of the module has or is using private name 'Props' #1232

Closed
ly-sniper opened this issue Apr 24, 2022 · 40 comments · May be fixed by #5043
Closed

Default export of the module has or is using private name 'Props' #1232

ly-sniper opened this issue Apr 24, 2022 · 40 comments · May be fixed by #5043
Labels
question Further information is requested

Comments

@ly-sniper
Copy link

when upgrade volar to ^0.34.9 , there is a ts warning Default export of the module has or is using private name 'Props' at the top of template

//error info -> Default export of the module has or is using private name 'Props'. ts(4082)
<template>test</template>
<script lang="ts" setup>
  //step1: declear type
  interface Props {
    foo: string;
  }
 // setp2: defineProps
  defineProps<Props>(); 
</script>

but if definePorps like below, the warning disappear

<template>test</template>
<script lang="ts" setup>
  defineProps<{
    foo: string;
  }>();
</script>
@johnsoncodehk
Copy link
Member

Hi @hayabusa2009, try remove "declaration": true in tsconfig or move interface Props to script block.

<script lang="ts">
//step1: declear type
interface Props {
  foo: string;
}
</script>

<script lang="ts" setup>
// setp2: defineProps
defineProps<Props>(); 
</script>

@mobayen
Copy link

mobayen commented May 4, 2022

Why Volar is complaining about the interface anyway?
Is it a bad practice?

@johnsoncodehk
Copy link
Member

@mobayen You just need move interface from <script setup> to <script> if it is a part of emit type, if in <script setup>, the interface is actually inside setup() scope so it can't be emit.

...
setup() {
	interface Props {
      foo: string;
    }
}

@ly-sniper
Copy link
Author

Hi @hayabusa2009, try remove "declaration": true in tsconfig or move interface Props to script block.

<script lang="ts">
//step1: declear type
interface Props {
  foo: string;
}
</script>

<script lang="ts" setup>
// setp2: defineProps
defineProps<Props>(); 
</script>

@johnsoncodehk thank you for your replay and I try your advices but failed.
I want to know is there a way to extends thrid-part library component types in the setup block?
for example

<script lang="ts" setup>
  import type { ModalProps } from 'third-part-library/Modal';
  interface Props extends ModalProps {
    visible: boolean;
  }
  const props = defineProps<Props>();

</script>

@johnsoncodehk
Copy link
Member

johnsoncodehk commented May 5, 2022

@hayabusa2009 Have you try move interface Props to <script> tag? If it not works please provide a minimal reproduction.

<script lang="ts">
  import type { ModalProps } from 'third-part-library/Modal';
  interface Props extends ModalProps {
    visible: boolean;
  }
</script>

<script lang="ts" setup>
  const props = defineProps<Props>();
</script>

@ly-sniper
Copy link
Author

@johnsoncodehk when remove composite:true from tsconfig.json, warning disappear. tks again!

@cn-2k
Copy link

cn-2k commented May 19, 2022

@hayabusa2009 Have you try move interface Props to <script> tag? If it not works please provide a minimal reproduction.

<script lang="ts">
  import type { ModalProps } from 'third-part-library/Modal';
  interface Props extends ModalProps {
    visible: boolean;
  }
</script>

<script lang="ts" setup>
  const props = defineProps<Props>();
</script>

Life savier, ty very much!

@buckeyez
Copy link

buckeyez commented Jun 2, 2022

@johnsoncodehk With the latest version, this is blowing up the IDE. According to the documentation:

As of now, the type declaration argument must be one of the following to ensure correct static analysis:
A type literal
A reference to an interface or a type literal in the same file

and it also gives a code example of it in the script setup documentation:

interface Props {
  msg?: string
  labels?: string[]
}

const props = withDefaults(defineProps<Props>(), {
  msg: 'hello',
  labels: () => ['one', 'two']
})

I believe it should not throw here based on vue's documentation. Would you be willing to agree and would you like me to open an issue for it?

@HugoMuller
Copy link

Hi,

I found a lighter alternative to moving the interfaces: exporting them also works with Volar 0.38.1.

<script lang="ts" setup>
  export interface Props {
    msg?: string
    labels?: string[]
  }

  const props = withDefaults(defineProps<Props>(), {
    msg: 'hello',
    labels: () => ['one', 'two']
  })
</script>

But I totally agree with @buckeyez. Volar should comply with Vue, and not the other way around.

@iamgabrielsoft
Copy link

removing declaration from tsconfig.json file works for me

@buckeyez
Copy link

buckeyez commented Jul 7, 2022

removing declaration from tsconfig.json file works for me

This is not a valid solution. Its fine if what you are building is the end all, but when building components and libs it would defeat the purpose of using TS to not have the declarations for consumers.

@chesterlaykin
Copy link

Hi, what is the current recommended way to use interface for props?
The above suggestion to use "export interface" seems to work with no Volar error.
Is that the recommended way then?

It didn't work having it in a separate script, I get varying errors: Expected ";" but found "(" , Expected ";" but found "__returned__" , Expected ";" but found "defaults".

I have "Vue Language Features (Volar)" v0.40.13
and Vue: 3.2.38

@vaban-ru
Copy link

Hello, I have same issue when try to build in lib mode

@iamgabrielsoft
Copy link

Can you provide a minimal reproduction code?

@vaban-ru
Copy link

vaban-ru commented Sep 11, 2022

I will try to describe the problem in more detail. I have a small component library. Vue 3 + TS + Vite.
In package.json I have this version of libraries:

"vue": "^3.2.37",
"vue-tsc": "^0.40.13"
"vite": "^3.1.0",
"typescript": "^4.8.3",

In tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "useDefineForClassFields": true,
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"],
    "declaration": true,
    "emitDeclarationOnly": true,
    "declarationDir": "./dist/types",
    "isolatedModules": true,
    "skipLibCheck": true,
    "types": [
      "vite/client"
    ],
    "baseUrl": ".",
    "paths": {
      "~/*": ["./*"],
      "@/*": ["./src/*"]
    }
  },
  "include": [
    "src/index.ts",
    "src/components/**/*.ts",
    "src/components/**/*.vue",
    "src/composables/**/*.ts",
    "src/mocks/**/*.ts",
    "src/env.d.ts"
  ]
}

In vite.config.ts

const path = require("path");
const { defineConfig } = require("vite");
import vue from "@vitejs/plugin-vue";

module.exports = defineConfig(() => {
  const rootPath = path.resolve(process.cwd());
  const srcPath = `${rootPath}/src`;
  return {
    resolve: {
      alias: {
        "~": rootPath,
        "@": srcPath,
      },
    },
    plugins: [vue()], 
    build: {
      lib: {
        entry: path.resolve(__dirname, "src/index.ts"),
        name: "UiKitNext",
      },
      rollupOptions: {
        external: [
          "vue",
        ], 
        output: {
          exports: "named",
          globals: {
            vue: "Vue",
          },
        },
      },
      emptyOutDir: false,
    },
  };
});

Example of component:

<template>
  <div v-show="active" class="tab">
    <slot />
  </div>
</template>

<script lang="ts">
import { IEvent } from "@/components/types";

export interface ISvTabProps {
  title: string;
  id: string;
  actions?: IEvent[];
  hidden?: boolean;
  parentId?: number;
}
</script>

<script setup lang="ts">
import { ComponentInternalInstance, getCurrentInstance, ref } from "vue";

const props = withDefaults(defineProps<ISvTabProps>(), {
  hidden: false,
});
... // some code stuff
</script>

Build script in package.json

"build": "rimraf dist && vue-tsc && vite build",

When I run the vue-tsc, everything works fine and the dist/types are generated.

When I run the build script I get the following error:

Unexpected "="
29 |    setup(__props: any) {
30 |
31 |  const props = __props as { t props = wit, aults(defi, ops<ISvTabProps>(), hiddenn: false,,
   |                                     ^
32 |
33 |  const active =  }

transforming (131) src\components\Widgets\SvDepositForm\SvDepositForm.vueerror during build:
Error: Transform failed with 1 error:
D:/dev/norvikbank-next/ui-kit-next/src/components/Base/SvTab/SvTab.vue?vue&type=script&setup=true&lang.ts:31:35: ERROR: Unexpected "="

@chesterlaykin
Copy link

My error had to do with Vitest: if I choose vitest when installing (npm init vue@latest) , the tsconfig is different and has some files included with "references":

{
  "files": [],
  "references": [
    {
      "path": "./tsconfig.config.json"
    },
    {
      "path": "./tsconfig.app.json"
    },
    {
      "path": "./tsconfig.vitest.json"
    }
  ]
}

I tried to change stuff in those three files, but didn't manage to get rid of the errors.
If I remove the references array and add this from the original vue tsconfig the errors disappear:

  "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
  "files": [],
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }

Here is a reproduction

@vaban-ru
Copy link

Create some reproduction repo

@vaban-ru
Copy link

Maybe all the same it's not in the library but in Vue itself
vitejs/vite#9836
vuejs/core#5830

mklein994 pushed a commit to mklein994/playground-vue that referenced this issue Sep 17, 2022
Putting them in separate <script> tags lets them be excluded from the
type definition for the component.

See the error when creating types (e.g. `pnpm vue-tsc --composite false
-p tsconfig.app.json --declaration --emitDeclarationOnly`; note that
this will generate *.d.ts files next to the source files), and this
comment:

<vuejs/language-tools#1232 (comment)>
@StepanMynarik
Copy link

StepanMynarik commented Oct 4, 2022

Same problem here. I discovered it when using the new reactivity transform feature.
Anyway, this error occurs when using interface with defineProps in general I found out.

It is also worth noting that this is IDE error only. Compiler doesn't complain and everything works as expected.
The only problem is that ts4082 highlights my entire script setup in red :D

Can be solved by exporting the interface, but that doesn't seem right to me since no export is used in Vue docs.
Plus the aforementioned fact that it works, since (I believe) all types in script sertup are auto exported by default. So it is just IDE that should stop complaining.

@johnsoncodehk
Copy link
Member

Create some reproduction repo

The error is throw by vite build not vue-tsc, please consider reporting it to vite repo.

@johnsoncodehk
Copy link
Member

johnsoncodehk commented Oct 5, 2022

My error had to do with Vitest: if I choose vitest when installing (npm init vue@latest) , the tsconfig is different and has some files included with "references":

I can only got Cannot find module '../HelloWorld.vue' or its corresponding type declarations. error in the repo:

$ npm run type-check

> [email protected] type-check
> vue-tsc --noEmit -p tsconfig.vitest.json --composite false

src/components/__tests__/HelloWorld.spec.ts:4:24 - error TS2307: Cannot find module '../HelloWorld.vue' or its corresponding type declarations.

4 import HelloWorld from '../HelloWorld.vue'
                         ~~~~~~~~~~~~~~~~~~~


Found 1 error in src/components/__tests__/HelloWorld.spec.ts:4

@johnsoncodehk
Copy link
Member

@StepanMynarik could you provide repro case?

@vknowles-rv
Copy link

vknowles-rv commented Jan 24, 2023

Why is this closed? Based on how Vue 3 outlines how to use <script setup>, volar is not working properly.

Littering a project with <script> as a work around is exhausting, cruft, and confusing in medium/large projects.

export interface works, but isn't necessary in other IDEs. Not to mention, if any code inserted above export interface that isn't an import breaks the workaround.

Apologies for coming off rude, but workarounds doesn't constitute closing an issue.

@rezelute
Copy link

I agree with this, the plugin isnt working how the docs say it should work ..?

@panzerdp
Copy link

panzerdp commented Jan 27, 2023

A workaround is to annotate Props using type instead of interface:

<template>test</template>
<script lang="ts" setup>
  type Props = { // <----- Use type instead of interface
    foo: string;
  }
  defineProps<Props>(); 
</script>

Works in Volar 1.0.24.

bencodezen pushed a commit to vuejs/docs that referenced this issue Feb 1, 2023
Existing code snippet gives this error:

    Default export of the module has or is using private name 'Props'.ts (4082)

Error fixed thanks to:
vuejs/language-tools#1232 (comment)
jay-es pushed a commit to vuejs-translations/docs-ja that referenced this issue Feb 1, 2023
Existing code snippet gives this error:

    Default export of the module has or is using private name 'Props'.ts (4082)

Error fixed thanks to:
vuejs/language-tools#1232 (comment)
jay-es added a commit to vuejs-translations/docs-ja that referenced this issue Feb 2, 2023
Existing code snippet gives this error:

    Default export of the module has or is using private name 'Props'.ts (4082)

Error fixed thanks to:
vuejs/language-tools#1232 (comment)

Co-authored-by: riz <[email protected]>
@Ge6ben
Copy link

Ge6ben commented Jun 4, 2023

Why is this closed? Based on how Vue 3 outlines how to use <script setup>, volar is not working properly.

Littering a project with <script> as a work around is exhausting, cruft, and confusing in medium/large projects.

export interface works, but isn't necessary in other IDEs. Not to mention, if any code inserted above export interface that isn't an import breaks the workaround.

Apologies for coming off rude, but workarounds doesn't constitute closing an issue.

Same here!

@so1ve
Copy link
Member

so1ve commented Sep 2, 2023

Hey guys - for those who subscribes this issue - this is likely a limitation in Typescript. interface can be extended, but type aliases can't:

interface Foo {
  foo: 1
}
// No error! Foo has been extended
interface Foo {
  bar: 1
}
// -------
type Bar = {}
// Oops, error!
type Bar = {}

Why export interface works? Volar will hoist all export statements to top-level, so they can be imported from other files. However, though hoisting all interfaces seems to be a viable solution, it's un unacceptable (if the interface references some type alias or generics defined in script setup, what should we do?).

In looking for a doable solution and I can implement it in a PR. Any help is appreciated!

@amalitsky
Copy link

amalitsky commented Oct 16, 2023

Please reopen this issue.

Having it closed sends the wrong message, and motivates folks to open new issues for the same topic.

My issue is the same as described above: I can't define props interface extending a third-party library interface.
It's in the non-setup script tag.

I don't seem to be able to ignore this error with /* @vue-ignore */ either.

And this is a library of components.

@frankypixels
Copy link

It really doesn't make the best sense to close the issue if the docs say one thing and the plugin faults the same thing. It's very confusing to follow what you think is convention then get dinged for it and use work arounds.

@so1ve so1ve reopened this Nov 16, 2023
@so1ve
Copy link
Member

so1ve commented Nov 16, 2023

@frankypixels Any reproduction? I can't reproduce this issue anymore.

@frankypixels
Copy link

frankypixels commented Nov 16, 2023

This is exactly that I had yesteday

interface Notes {
id: string
content: string
}

const notes = defineProps<Notes>()

@Grenek
Copy link

Grenek commented Nov 27, 2023

It worked for me after updating volar to pre-release version 1.8.23

@johnsoncodehk
Copy link
Member

Starting from a certain version, when there is only one script setup block, the setup code will be generated to the file root instead of the function scope to avoid this problem.

@mityaua
Copy link

mityaua commented Sep 4, 2024

2.1.4 - still actual. But with defineComponent syntax.

UPD:
Some cases solution (export interface):

<script setup lang="ts" generic="T">
export interface Props<T>

@charnog
Copy link

charnog commented Dec 11, 2024

I created a repository to demonstrate the issue where a <script setup> component (with props defined via interface Props) is used within a defineComponent, causing a “Default export…” error.

Repository: https://github.com/charnog/vue-default-export

We initially started our project using only the defineComponent syntax (Vue 2). When Vue 3 was released, we began using the Composition API for all new components. Naturally, we use the “old” defineComponent components within the new ones. However, after some package updates, this error started appearing.

This might also be related to @mityaua’s issue, but I’m not entirely sure.

@KazariEX @johnsoncodehk let me know if you’d like me to create a distinct issue for this.

@webdesignberlin
Copy link

I created a repository to demonstrate the issue where a <script setup> component (with props defined via interface Props) is used within a defineComponent, causing a “Default export…” error.

Repository: https://github.com/charnog/vue-default-export

We initially started our project using only the defineComponent syntax (Vue 2). When Vue 3 was released, we began using the Composition API for all new components. Naturally, we use the “old” defineComponent components within the new ones. However, after some package updates, this error started appearing.

This might also be related to @mityaua’s issue, but I’m not entirely sure.

@KazariEX @johnsoncodehk let me know if you’d like me to create a distinct issue for this.

if u use export props it works: charnog/vue-default-export#1

@charnog
Copy link

charnog commented Dec 11, 2024

@webdesignberlin Yep, thank you! This “workaround” was already described here. There’s also the type Props workaround, or you can use defineProps<{ msg: string }> instead. The official docs explain how to type Props in a more formal way without requiring an export.

My question isn’t about “how to fix it in a component” but rather “what is the best approach and is it possible to address this in volar/vue-tsc?” If not, then what should be considered the official approach?

@KazariEX
Copy link
Collaborator

This is a limitation of TS.

// setup.ts
import { defineComponent } from "vue";

interface Props {
  msg: string;
}

export default defineComponent({
  __typeProps: {} as Props
});
// define.ts
import { defineComponent } from "vue";
import Setup from "./setup";

export default defineComponent({
  components: {
    Setup,
  },
});

The currently discovered solution that can be implemented in this repository is:

export default defineComponent({
  __typeProps: {
    ...{} as Props
  }
});

@KazariEX KazariEX reopened this Dec 11, 2024
@KazariEX
Copy link
Collaborator

@charnog please feel free to open a new issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.