Using 'title' in a Child Route causes a Type Error
Vaadin 21.0.2, @vaadin/router 1.7.4 here. With a route configuration like this
{ path: 'foo',
component: 'foo-view',
title: 'Foo',
children: [
{ path: 'bar',
component: 'bar-view',
title: 'Bar'
}]
}
I get the following compile error
TS2322: Type '{ path: string; component: string; icon: string; title: string; children: {
path: string; component: string; title: string; children: {
path: string; component: string; }[]; }[]; }' is not assignable to type 'ViewRoute'.
Type '{ path: string; component: string; icon: string; title: string; children: {
path: string; component: string; title: string; children: {
path: string; component: string; }[]; }[]; }' is not assignable to type 'RouteWithRedirect & {
title?: string | undefined; icon?: string | undefined; children?: ViewRoute[] | undefined; }'.
Property 'redirect' is missing in type '{ path: string; component: string; icon: string; title: string; children: {
path: string; component: string; title: string; children: {
path: string; component: string; }[]; }[]; }' but required in type 'RouteWithRedirect'.
The error disappears when I remove the title: 'Bar' line.
- Adding an empty 'redirect' attribute causes other problems, and I don't want to redirect, actually.
- I don't understand why the compiler infers a type of 'RouteWithRedirect' here?! 'RouteWithComponent' would seem more appropriate, no?!
- Still, it is not clear to me why this would be caused by adding a 'title' attribute in the child route. Can I not use a 'title' attribute on child routes? The definition of the
ViewTypetype seems to suggest so.
Ok, so one way to work around this issue is to cast the child object to ViewRoute:
{ path: 'foo',
component: 'foo-view',
title: 'Foo',
children: [
<ViewRoute>{ path: 'bar',
component: 'bar-view',
title: 'Bar'
}]
}
But why is this necessary?
I think this is not an issue in vaadin/router but an issue in how the router is being used in the code generated from https://start.vaadin.com/ which defines:
export type ViewRoute = Route & {
title?: string;
icon?: string;
children?: ViewRoute[];
};
The children?: ViewRoute[]; doesn't have the intended effect as it's not possible to override a field of a parent type/interface so simply in TypeScript. It's basically a bug in the ViewRoute definition in the application code but the TS error you get in this situation is very confusing and hard to debug.
This is why it works when you explicitly cast the type of children. I also ran into this once and then solved it by doing something like children: [ ... ] as ViewRoute[] iirc.
Just now when searching for the problem again I found this https://stackoverflow.com/questions/51591792/typescript-overwrite-a-field-from-an-extended-interface and it seems that it's possible to fix the issue without explicit casting by changing the ViewRoute definition to this (using Omit<>):
export type ViewRoute = Omit<Route, 'children'> & {
title?: string;
icon?: string;
children?: ViewRoute[];
};
I just tried and using this it gets rid of the error that would otherwise happen when you add title into one of the routes under children.
I created an issue about this in the private repository of start.vaadin.com. This public issue could probably be moved to https://github.com/vaadin/vaadin.com/issues