-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
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
declaration of beforeRouteEnter(to,from,next) hook should be updated #1863
Comments
@ktsn Could you please give me a hand on this one whenever it's possible for you, please? 🙂 |
Since contextual beforeRouteEnter(to, from, next) {
next((vm: { str: string } & Vue) => {
vm.str = "sdf"
});
}, Or we could relax the
This is probably because of Maybe we should relax the type of @HerringtonDarkholme What do you think? |
Actually, i'm not quite understand. When we're coding a app class(or object?), we could ensure that the Is it possible(or proper) to replace declare module "vue/types/options" {
interface ComponentOptions<V extends Vue> {
router?: VueRouter;
beforeRouteEnter?: NavigationGuard;
beforeRouteLeave?: NavigationGuard;
beforeRouteUpdate?: NavigationGuard;
}
} There's an unused generic variable export type NavigationGuard<V extends Vue> = (
to: Route,
from: Route,
next: (to?: RawLocation | false | ((vm: V) => any) | void) => void
) => any At the same time, these two declarations could be updated like below: export declare class VueRouter {
// ...
beforeEach (guard: NavigationGuard<Vue>): Function;
beforeResolve (guard: NavigationGuard<Vue>): Function;
} export interface RouteConfig {
// ...
beforeEnter?: NavigationGuard<Vue>;
} I'm not sure about whether the type |
I'm still confused. There must be something i misunderstood or even never know. I'm focusing on the In-Component guards So for the example you posted, do you mean to define // Component List
@Component<List>({
beforeRouteEnter(to, from, next) {
next((vm: List) => {
vm.blog; // accessible
});
},
})
class List extends Vue {
blog: any;
} // Component Author
@Component<Author>({
beforeRouteEnter(to, from, next) {
next((vm: Author) => {
vm.blog;// accessible
});
},
})
class Author extends Vue {
blog: any;
} // Component Blog
@Component<Blog>({
beforeRouteEnter(to, from, next) {
next((vm: Blog) => {
vm.p;// accessible
});
},
})
class Blog extends Vue {
p: any;
} |
@doommm I'm so sorry. I mistaken the type of However, given this typing, I wonder if we can manage to give a good typing. Using generic isn't available here since In classical OOP, such use case is covered by F-bounded polymorphism. class Component<T extends Component<T>> {
beforeRouteEnter(next: (vm: T) => any) {}
}
class Blog extends Component<Blog> {
beforeRouteEnter(next: (vm: Blog) => any) {}
} However, Vue isn't defined like this. None equivalent presents for object literal. |
Hmm, fiddling with quantification might solve this type NavigationGuard = (
this: never,
to: Route,
from: Route,
next: <V extends Vue>(to: (vm: V) => any) => void
) => any
interface ComponentOptions<V extends Vue> {
router?: VueRouter;
beforeRouteEnter?: NavigationGuard;
beforeRouteLeave?: NavigationGuard;
beforeRouteUpdate?: NavigationGuard;
} Then interface Test extends Vue {
test: number
}
Vue.extend({
beforeRouteEnter(to, from, next) {
next((v: Test) => {
})
}
}) |
Note the type parameter quantification here. We make |
I don't know if it gives any help while implementing a component with Vue.extend, but using vue-class-component I was in need of a type to "describe" the next function so to have my properties in "vm" reference, so I made this:
This way, on beforeRouteEnter I do:
Where "Associa" (which is optional, it's Vue type if not passed) is my component as described below:
This way, I don't have any typescript errors and works pretty nicelly. Btw: For those who are trying to use this way, you might do: File shims-router.d.ts:
Then: Again, so sorry if doesn't help in nothing, cause it helped me a lot. |
Anything we can do to improve current situation. I don't feel like including the helper type but it may be the right choice. Otherwise we could document this, we don't have a ts section in docs yet |
Not too sure if this is the right location for this question, but it is related to the discussion above. I have a component annotated as following: @Component({
async beforeRouteEnter (to: Route, from: Route, next: any): Promise<any> {
const { data } = await CustomerService.get(parseInt(to.params.id))
next((vm: CustomerDetailsComponent) => {
vm.customer = data
}
})
export default class CustomerDetailsComponent extends Mixins(Acl, Translate) {
customer: CustomerEntity = {
// ... some properties
}
} This works fine and typescript accepts the vm.customer reference without issues. If I apply a similar logic to the beforeRouteUpdate method, the this.customer reference won't be accepted: async beforeRouteUpdate (to: Route, from: Route, next: any): Promise<any> {
const { data } = await CustomerService.get(parseInt(to.params.id))
this.customer = data
next()
} This results in an error: Is there a way to typehint the call so that typescript will get that the I have tried to pass in the correct instance to the method, but this doesn't really work: async beforeRouteUpdate<CustomerDetailsComponent> What would be the correct way? |
@uriannrima's suggested solution did the trick for me. I think that solution, or one along the same lines, needs to be implemented to make life easier when developing Vue apps with |
Just use the example:
|
Would you be so kind as to provide an example where the composition api is used?
|
Try it
|
Same issue here, @webrsb solution unfortunately doesn't work since Vue is a namespace, not a type (at least in my setup with Vue 3). Have been messing around with ComponentPublicInstance, but can't get it to accept the addition property |
@websmurf, @webrsb Please try this: import { ComponentPublicInstance, defineComponent, ref } from 'vue'
import { NavigationGuardNext, RouteLocationNormalized } from 'vue-router'
type CustomNameParamProvider = {
customNameParam: string
} & ComponentPublicInstance
function isCustomNameParamProvider (vm: ComponentPublicInstance): vm is CustomNameParamProvider {
return (vm as CustomNameParamProvider).customNameParam !== undefined
}
export default defineComponent({
beforeRouteEnter: (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
next(vm => {
if (isCustomNameParamProvider(vm) && typeof from.name === 'string') {
vm.customNameParam = from.name
}
})
},
setup () {
const customNameParam = ref('')
return {
customNameParam
}
}
}) This is using an "user-defined type guard" for narrowing. |
Version
3.0.1
Reproduction link
https://jsfiddle.net/doommm/50wL7mdz/74369/
Steps to reproduce
I found that in declaration file(
types/router.d.ts
), there's a type namedNavigationGuard
used forbeforeRouteEnter
and other two hooks. The function declaration ofnext
is((vm: Vue) => any) | void) => void
, and should it be updated so we could access all members declared in class(or object)?I wrote three examples to explain my confusion.
vue-class-component
, if i add an type identifier manually, it works. no error. if not, error.vue-class-component
, whether i add identifier or not, got error. But if i roll back to typescript 2.5.3, and add type identifier, it works.I think the declaration should be updated(Generics?
T extends Vue
or ?), but i'm not sure about that. Sorry for my poor english If I dont describe the problem clearly.What is expected?
all class(object) members should be accessed in
vm.propertyName
What is actually happening?
We could only access members of Vue.
The text was updated successfully, but these errors were encountered: