https://github.com/iwata/codesandbox-nuxt
$ git clone [email protected]:iwata/codesandbox-nuxt.git
$ yarn install
$ yarn dev
No type checking errors
It shows this error:
ERROR in /Users/iwata/.go/src/github.com/iwata/codesandbox-nuxt/node_modules/@nuxt/vue-app/types/index.d.ts(73,18):
TS2430: Interface 'NuxtApp' incorrectly extends interface 'Vue'.
Types of property '$loading' are incompatible.
Property 'open' is missing in type 'NuxtLoading' but required in type '{ open: (params: LoadingConfig) => { close: () => any; }; }'.
If you import Buefy looks like plugins/buefy.ts, it declares $loading for Vue instance.
https://github.com/buefy/buefy/blob/dev/types/index.d.ts#L10
So NuxtApp extends the Vue, therefore $loading conflicts.
https://github.com/nuxt/nuxt.js/blob/v2.4.0/packages/vue-app/types/index.d.ts#L73-L74
Well, there is the same issue for ElementUI if i'm right.
I don't know what we're supposed to do, both of frameworks (Nuxt & Buefy) are setuping the same variable so 😬
@manniL WDYT ?
The only solution could be to have the $loading definition outside of @nuxt/vue-app to avoid that but it sounds weird to not have it inside.
@kevinmarrec The problem lies even deeper. If ElementUI and Buefy both use $loading, will they override the Nuxt.js $loading. Or will Nuxt override theirs?
We should think about how to properly avoid naming collisions like that.
Is it necessary to have a plugin namespace in Vue first?
@manniL I don't know, I guess they override Nuxt as they are Vue plugins (Vue.use) and instanciated on top of Nuxt ?
I have this issue with Element-ui also. Are there any clarifications on this? Maybe a temporary fix?
Sorry if we didn't find a workaround yet.
UI libraries shouldn't directly non-namespaced add properties to the Vue instance interface.
For example, Vuetify uses this.$vuetify.x, meanwhile Buefy & ElementUI directly use this.x, which is IMO not good. (this being a Vue instance)
The issue is that these 2 UI libraries can't change this behavior without breaking changes.
@kevinmarrec I understand, and I agree with you. Is there a way for us to make a workaround?
@sebastianks Ideally creating issues in the corresponding repos 🙈
I run into the issue with Element-ui as well.
I guess namespacing sounds like the way to go - but as @kevinmarrec mentioned this will come with breaking changes - so if rolled out as @deprecated via (several / major) releases until _removed_ will take time..
Maybe it would be a good idea to escalate this to the vuejs team directly - to add documentation / guidelines to avoid such clashes going forward and with more frameworks, .. to come.
I believe this is not a Nuxt-ts or element-ui issue
@iwata @hartmut-co-uk may you need to define the $loading type
import {ElLoading} from 'element-ui/types/loading'
import {ElMessage} from 'element-ui/types/message'
import {ElMessageBox} from 'element-ui/types/message-box'
import {ElNotification} from 'element-ui/types/notification'
declare module 'vue/types/vue' {
interface Vue {
readonly $loading: typeof ElLoading.service
// maybe you will use these things also
readonly $alert: typeof ElMessageBox.alert
readonly $confirm: typeof ElMessageBox.confirm
readonly $message: ElMessage
readonly $msgbox: ElMessageBox
readonly $notify: ElNotification
readonly $prompt: typeof ElMessageBox.prompt
}
}
@bichikim The issue is that it's a naming collision between the $loading from nuxt and the one from ElementUI/Buefy.
@manniL Oh i see~ in that case, fix element-ui loading at element-ui/lib/loading
This error prevents the command nuxt-ts generate from working...
In my case, it's conflicting with Buefy.
So as a dirty temporary fix, I've edited node_modules/@nuxt/vue-app-edge/types/index.d.ts with:
+export interface LoadingConfig {
+}
export interface NuxtLoading extends Vue {
fail?(): void;
finish(): void;
increase?(num: number): void;
pause?(): void;
start(): void;
+ open: (params: LoadingConfig) => { close: () => any; };
}
For now i added the following to my tsconfig.json:
"compilerOptions": {
"skipLibCheck": true
}
@P-de-Jong's solution works for me
@P-de-Jong's solution works for me
This also worked for me, however, it seems to be more of a work-around than a solution.
We will change it to $nuxt.$loadingthis.$nuxt.$progress in Nuxt 3 ☺️
@manniL In fact it's already this.$nuxt.$loading, and this.$loading is only a shortcut (AFAIK).
$nuxt being a Vue instance, in any case we need to say that NuxtApp ($nuxt) extends Vue.
The issue is IMO 100% Buefy fault which is not extending but overriding Vue typedefs through https://github.com/buefy/buefy/blob/dev/types/index.d.ts#L10.
By doing this, they force the Vue instance to always have $loading property and also forcing it to be of type LoadingProgrammatic, which is wrong.
Meanwhile within Nuxt, we only say that $nuxt is a Vue instance with a $loading property.
Unless we force us to change the name from $loading to something else, there won't be workarounds.
Buefy (and ElementUI) should highly initiate a breaking change which namespace their properties.
@kevinmarrec Whoops. Updated my statement based on the things discused in the last meeting☺️
since if $loading is only used in NuxtApp
this could be a temp workaround
but won't be a perma fix if there is any naming collision in the future
interface NuxtAppAnyLoading extends Vue {
$loading: any
}
export interface NuxtApp extends NuxtAppAnyLoading {
$loading: NuxtLoading
isOffline: boolean
isOnline: boolean
}
I confirmed fixed issuse with Buefy v0.8.0.
This issue still persists with element-ui
This issue still persists with element-ui
For Element-UI, the only work-around that got me out of the mess is to override Nuxt's $loading. I did this by creating a new type file in my app and defining an interface which extends NuxtApp type, where I defined the type of $loading as 'any':
In file ~/types/nuxt.d.ts
import { NuxtApp } from "@nuxt/vue-app/types/index";
export interface NuxtLoading extends NuxtApp {
$loading: any
}
This issue still persists with element-ui
For Element-UI, the only work-around that got me out of the mess is to override Nuxt's $loading. I did this by creating a new type file in my app and defining an interface which extends NuxtApp type, where I defined the type of $loading as 'any':
In file ~/types/nuxt.d.ts
import { NuxtApp } from "@nuxt/vue-app/types/index"; export interface NuxtLoading extends NuxtApp { $loading: any }
i tried import { NuxtApp } from "@nuxt/vue-app/types/index";
but can't find @nuxt/vue-app :sob:
import { NuxtApp } from "@nuxt/types/app";
export interface NuxtLoading extends NuxtApp {
$loading: any
}
this is no error, still not working
91:18 Interface 'NuxtApp' incorrectly extends interface 'Vue'.
Types of property '$loading' are incompatible.
Type 'NuxtLoading' is not assignable to type '(options: LoadingServiceOptions) => ElLoadingComponent'.
Type 'NuxtLoading' provides no match for the signature '(options: LoadingServiceOptions): ElLoadingComponent'.
89 | }
90 |
> 91 | export interface NuxtApp extends Vue {
| ^
92 | $options: NuxtAppOptions
93 | $loading: NuxtLoading
94 | isOffline: boolean
@ChangJoo-Park
Since new TS support, NuxtApp is now accessible via
import { NuxtApp } from '@nuxt/types/app/index'
Thanks @kevinmarrec
@kevinmarrec Doesn't solve my problem :/
In file ~/types/nuxt.d.ts
import { NuxtApp } from '@nuxt/types/app/index'
export interface NuxtLoading extends NuxtApp {
$loading: any
}
nuxt: 2.9.2
element-ui: 2.4.11
Do I need to add nuxt.d.ts somewhere in tsconfig.json?
@danito as a temporary bypass I just forked the @nuxt/types and edited:
node_modules/@nuxt/types/app/index.d.ts:91
From:
$loading: NuxtLoading
To:
$loading: any
Has there been an issue open on ElementUI's repos about this? I'd imagine this is something they could fix although Nuxt locking down a generic global name like $loading might cause future issues. Although it's difficult to say where that line should be or not.
For the record the new issue on ElementUI is located here: https://github.com/ElemeFE/element/issues/17630
BTW: Is Element-UI actively maintained or should I switch to another UI-framework? No commit since 23 days seems to be strange for such a big project!?
23 days seems indeed strange.
Has anyone found an official workaround (that may already present in this thread) that currently works ?
In tsconfig.json:
"compilerOptions": {
"skipLibCheck": true
}
works for me, but hmm
Maybe instead,
"paths": {
"element-ui": [".sink.d.ts"] // empty file
}
works, too?
The real solution is either Nuxt or ElementUI needs to fix their namespace clashing and pick a less generic name than "loading" for root-level global stuff.
But yes, either edit the ts configs as above or fork Nuxt and change NuxtApp's interface to $loading: any
Maybe it would be worth to start thinking in terms of the composition API? If Nuxt and/or ElementUI provided this stuff through a composable there would be no problem.
For example, I'm relying on a custom made const nuxt = useNuxtContext() composable. I access everything related to Nuxt using that.
That would be ideal although legacy support for the current Vue 2 is a long term goal for the team I believe.
Yes, that's still a problem.
As it's a unfixable issue around the module itself, i'm closing it here. Please open an issue around Nuxt core repo (there may already be one) about changing loading Nuxt API for next Nuxt version, if it seems the most relevant thing to do.
oh . it is so sad。
Most helpful comment
For now i added the following to my
tsconfig.json: