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

Type augmentation is broken when using typescript's moduleResolution: "Bundler" option #13106

Closed
thebanjomatic opened this issue Oct 24, 2023 · 0 comments · Fixed by #13107
Closed

Comments

@thebanjomatic
Copy link
Contributor

thebanjomatic commented Oct 24, 2023

Version

2.7.15

Reproduction link

codesandbox.io

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.

image
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":

image
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.

thebanjomatic added a commit to thebanjomatic/vue that referenced this issue Oct 24, 2023
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:
```ts
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 (when using skipLibChecks: true), and the types aren't available on the vue constructor options or the component instance.

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/vue' cannot be found.ts(2664)
module "vue/types/vue"
```

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 file with that name, it fails.

What this PR does is provide multiple options to look for when an import matches the "./types/*" export.

1) First we append '.d.ts' and check for that file. I suspect this will be the most common occurence (people that didn't use the extension) so I'm listing it first.
2) In the event that someone had done `declare module 'vue/types/vue.js'` or `declare module 'vue/types/vue.d.ts'` in their code to work around this issue in prior versions of vue 2.7.x, we still allow for those to match directly.

Fixes: vuejs#13106
yyx990803 pushed a commit that referenced this issue Dec 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant