Subscribe on changes!

Missing support in `@vue/runtime-dom` for TypeScript's `--exactOptionalPropertyTypes` option

avatar
Jun 7th 2022

Vue version

3.2.36

Link to minimal reproduction

https://stackblitz.com/edit/vitejs-vite-hguguz?file=tsconfig.json,src%2FApp.vue&terminal=dev

Steps to reproduce

  1. Open a terminal
  2. Run vue-tsc --noEmit

What is expected?

The command vue-tsc --noEmit runs without errors.

What is actually happening?

The command vue-tsc --noEmit gives type errors (output below was copied from StackBlitz reproduction):

src/App.vue:8:4 - error TS2375: Type '{ alt: undefined; }' is not assignable to type 'ElementAttrs<ImgHTMLAttributes>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
  Type '{ alt: undefined; }' is not assignable to type 'ImgHTMLAttributes' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
    Types of property 'alt' are incompatible.
      Type 'undefined' is not assignable to type 'string'.

8   <img :alt="msg" />
     ~~~

Found 1 error in src/App.vue:8

System Info

No response

Any additional comments?

TypeScript 4.4 introduced a new option --exactOptionalPropertyTypes which specifies that optional property types should be interpreted exactly as written, meaning that | undefined is not added to the type. The *HTMLAttributes interfaces in @vue/runtime-dom are lacking the | undefined type, meaning that vue-tsc with enabled --exactOptionalPropertyTypesflag will fail.

Regarding the StackBlitz reproduction, the ImgHTMLAttributes interface should be defined at least as

export interface ImgHTMLAttributes extends HTMLAttributes {
  alt?: undefined | string
  crossorigin?: 'anonymous' | 'use-credentials' | ''
  decoding?: 'async' | 'auto' | 'sync'
  height?: Numberish
  sizes?: string
  src?: string
  srcset?: string
  usemap?: string
  width?: Numberish
}

instead of

export interface ImgHTMLAttributes extends HTMLAttributes {
  alt?: string
  crossorigin?: 'anonymous' | 'use-credentials' | ''
  decoding?: 'async' | 'auto' | 'sync'
  height?: Numberish
  sizes?: string
  src?: string
  srcset?: string
  usemap?: string
  width?: Numberish
}

However, for sake of completion the | undefined type needs to be added to all optional properties, not only the alt? one.