Subscribe on changes!

Unable to use directives without arguments but with modifiers due to type error in vue

avatar
Aug 8th 2022

Vue version

3.2.37

Link to minimal reproduction

https://stackblitz.com/edit/vue-repro-vmodel-trim-type-error-directivearguments?file=package.json,App.vue&terminal=webpack

Steps to reproduce

This stackblitz link should automatically run these commands: npm install npm run webpack

What is expected?

npm run webpack should compile the project (.ts and .vue) files into a webpack bundle using ts-loader and vue-loader

Output:

webpack 5.74.0 compiled successfully

What is actually happening?

npm run webpack should compile the project (.ts and .vue) files into a webpack bundle using ts-loader and vue-loader

Output:

ERROR in App.vue.ts
[tsl] ERROR in App.vue.ts(13,7)
      TS2322: Type '[ModelDirective<HTMLInputElement | HTMLTextAreaElement>, any, undefined, { trim: true; }]' is not assignable to type '[Directive<any, any>] | [Directive<any, any>, any] | [Directive<any, any>, any, string] | [Directive<any, any>, any, string, DirectiveModifiers]'.
  Type '[ModelDirective<HTMLInputElement | HTMLTextAreaElement>, any, undefined, { trim: true; }]' is not assignable to type '[Directive<any, any>, any, string, DirectiveModifiers]'.
    Type at position 2 in source is not compatible with type at position 2 in target.
      Type 'undefined' is not assignable to type 'string'.

webpack 5.74.0 compiled with 1 error

Changing the source of App.vue from v-model.trim to v-model resolves the error.

System Info

No response

Any additional comments?

This error appears to be from a bug in vuejs/core/packages/runtime-core/src/directives.ts

export type DirectiveArguments = Array<
  | [Directive]
  | [Directive, any]
  | [Directive, any, string]
  | [Directive, any, string, DirectiveModifiers]
>

The 4th variant of DirectiveArguments is used to compile vue directives with both an argument and modifiers For example v-on:click.prevent

However, some vue directives such as v-model can have modifiers (eg .trim) but are not allowed to have an arg These are compiled as type [Directive, any, undefined, DirectiveModifiers] which causes the typescript error in the reproduction.

DirectiveBinding.arg is already string|undefined so the 4th version of DirectiveArguments could probably be changed to:

[Directive, any, string|undefined, DirectiveModifiers]
avatar
Aug 8th 2022

This was previously reported as https://github.com/vuejs/core/issues/4780 but was closed as not a bug.