vuejs / language-tools

⚡ High-performance Vue language tooling based-on Volar.js
https://marketplace.visualstudio.com/items?itemName=Vue.volar
MIT License
5.77k stars 388 forks source link

defineProps<T> partial object type inferred as 'unknown' in template #3563

Closed serialine closed 2 months ago

serialine commented 1 year ago

Volar version

1.8.11

Vue version

Nuxt 2.17.1 / Vue 2.7.14

Link to minimal reproduction

https://github.com/serialine/nuxt-2.17.1-ts

Steps to reproduce

tsconfig.json

{
  "vueCompilerOptions": {
    "target": 2.7,
    "plugins": [
      "@vue-macros/volar/define-options",
      "@vue-macros/volar/define-models",
      "@vue-macros/volar/define-props",
      "@vue-macros/volar/define-props-refs",
      "@vue-macros/volar/short-vmodel",
      "@vue-macros/volar/define-slots",
      "@vue-macros/volar/export-props",
      "@vue-macros/volar/jsx-directive"
    ]
  },
  "compilerOptions": {
    "target": "ES2018",
    "module": "ESNext",
    "moduleResolution": "Node",
    "lib": ["ESNext", "ESNext.AsyncIterable", "DOM"],
    "esModuleInterop": true,
    "allowJs": true,
    "experimentalDecorators": true,
    "sourceMap": true,
    "strict": false,
    "isolatedModules": true,
    "noImplicitThis": true,
    "skipLibCheck": true,
    "noEmit": true,
    "baseUrl": ".",
    "paths": {
      "~/*": ["./*"],
      "@/*": ["./*"]
    },
  },
  "exclude": ["node_modules", ".nuxt", "dist"]
}
<script lang="ts" setup>
interface Option1 {
  title?: string
  description?: string
}
interface Option2 {
  title: string
  description?: string
}

defineProps<{
  option1: Option1;
  option2: Option2;
  option3: Required<Option1>;
  option4: Partial<Option2>;
}>()
</script>

<template>
  <div>
    {{ option1.title }} <!-- Property 'title' does not exist on type 'unknown'.ts(2339) -->
    {{ option2.title }}
    {{ option3.title }}
    {{ option4.title }} <!-- Property 'title' does not exist on type 'unknown'.ts(2339) -->
  </div>
</template>

What is expected?

Prop option1 inferred as object and property 'title' inferred as string | undefined.

What is actually happening?

Prop option inferred as 'unknown', Property 'title' does not exist on type 'unknown'

Any additional comments?

duplicates from https://github.com/vuejs/core/issues/9169

it happens when "strict": false in the tsconfig.json. but the minimal requirements condition "noImplicitThis": true is configured.

so1ve commented 1 year ago

Ughhhhhhhhhhhhhhhhhh after some investigation this seemed to be a type issue in vue core...

image

lirobinxc commented 6 months ago

Bump, this issue is blocking us from using very basic TS functionality like Partial. Even the following causes this issue:

// OK if no optional properties on the nested object
defineProps<{
  customProp: {
    foo: string;
    bar: string;
    baz: string;
  };
}>();

// OK if some optional properties on the nested object
defineProps<{
  customProp: {
    foo?: string;
    bar?: string;
    baz: string;
  };
}>();

// NOT OK if all optional properties on the nested object
// TS Error 2339: Property 'foo' does not exist on type 'unknown'
// TS Error 2339: Property 'bar' does not exist on type 'unknown'
// TS Error 2339: Property 'baz' does not exist on type 'unknown'
defineProps<{
  customProp: {
    foo?: string;
    bar?: string;
    baz?: string;
  };
}>();
davidmatter commented 2 months ago

Tested: This is not an issue anymore in v2