Type augmentation is broken when using typescript's moduleResolution: "Bundler" option
thebanjomatic opened this issue · 0 comments
Version
2.7.15
Reproduction link
Steps to reproduce
yarn install
yarn test
What is expected?
The project should typecheck without errors
What is actually happening?
The type augmentation fails and as a result, there are type errors that need to be worked around.
When using typescript's "moduleResolution": "bundler" option, we currently get a bunch of type errors, particularly when trying to extend the types, or when consuming other packages which extend the types (vue-router, pinia, etc).
For example, vue-router extends the types as follows:
declare module 'vue/types/vue' {
interface Vue {
$router: VueRouter
$route: Route
}
}
declare module 'vue/types/options' {
interface ComponentOptions<V extends Vue> {
router?: VueRouter
beforeRouteEnter?: NavigationGuard<V>
beforeRouteLeave?: NavigationGuard<V>
beforeRouteUpdate?: NavigationGuard<V>
}
}
But this silently fails, and the types aren't available on the vue constructor options or the component instance.
Object literal may only specify known properties, and 'router' does not exist in type 'ComponentOptions<Vue<Record<string, any>, Record<string, any>, never, never, (event: string, ...args: any[]) => Vue<Record<string, any>, Record<string, any>, never, never, ...>>, ... 7 more ..., ComponentOptionsMixin>
The reason for this can be seen when copying the code into your own project with "moduleResolution": "bundler"
:
Invalid module name in augmentation, module 'vue/types/options' cannot be found.ts(2664)
module "vue/types/options"
What is happening is that once "moduleResolution" is set to "bundler", the "exports" maps in package.json starts being used, and there are some peculiarities with wildcard matching that we don't appear to be accounting for here. In particular, wildcard matching is going to require that the full path to the file is provided. So, when we specify declare module 'vue/types/vue'
it is going to look for a file on disk with the relative path: ./types/vue
, and since there is no extensionless file with that name, it fails.
You could technically work around this by explicitly specifying declare module 'vue/types/vue.js'
or declare module 'vue/types/vue.d.ts'
when you are doing the type augmentation, but I think it would be better to just fix the "exports" definition to allow you to specify the file name without the extension as otherwise we'd need to release updates to many other packages and user code vs just one.