Repository: vuejs/eslint-plugin-vue (JavaScript)

Issue:
False negative with vue/require-valid-default-prop on props with type assertion
<!--
  ❗Please don't ignore this template.❗

  If you ignore it, we're just going to respond asking you to fill it out, which wastes everyone's time.
  The more relevant information you can include, the faster we can find the issue and fix it without asking you for more info.
-->

<!--
  Before posting the issue, please confirm that the problem you're getting
  is not related with your code editor configuration.
  To make sure it's not, run: yarn eslint src/your-file.vue
-->

**Checklist**

- [x] I have tried restarting my IDE and the issue persists.
- [x] I have read the [FAQ](https://eslint.vuejs.org/user-guide/#faq) and my problem is not listed.
<!-- If you do not read the FAQ and open an issue that is listed in the FAQ, we may silently close the issue. -->

**Tell us about your environment**

- **ESLint version:** 7.23.0
- **eslint-plugin-vue version:** 7.8.0 
- **Node version:** 14.16.0
- **Operating System:** Windows 10 Pro

**Please show your full configuration:**
<!-- Paste content of your .eslintrc file -->
```js
module.exports = {
  root: true,
  env: {
    node: true,
  },
  extends: [
    "plugin:vue/essential",
    "eslint:recommended",
    "@vue/typescript/recommended",
    "@vue/prettier",
    "@vue/prettier/@typescript-eslint",
  ],
  parserOptions: {
    ecmaVersion: 2020,
  },
  rules: {},
};
```

**What did you do?**	

I annotated type to array prop with typescript according to the following documentations.
- https://vuejs.org/v2/guide/typescript.html#Annotating-Props
- https://v3.vuejs.org/guide/typescript-support.html#annotating-return-types

If the prop is an array, the default should be a function, but I set empty array directly by mistake.

<!-- Please include the actual source code causing the issue. -->
```vue
<script lang="ts">
import Vue from "vue";
import { PropType } from "vue";

export default Vue.extend({
  props: {
    foo: {
      type: Array as PropType<string[]>,
      default: [],
    },
  },
});
</script>
```

**What did you expect to happen?**

eslint reports type of the default value for 'foo' prop must be a function.

**What actually happened?**
<!--
  Please include the actual, raw output from ESLint.
  If you are only looking at the results of your editor extension, also check the CLI results.
-->

eslint did not report that. If there is no type assertion, it reports correctly.





Discussion:
Will this work with the [next case](http://dl3.joxi.net/drive/2021/04/05/0030/1408/1971584/84/92890a21bf.png)?



Patch:
diff --git a/lib/rules/require-valid-default-prop.js b/lib/rules/require-valid-default-prop.js
index ef9453b23..e40cad861 100644
--- a/lib/rules/require-valid-default-prop.js
+++ b/lib/rules/require-valid-default-prop.js
@@ -49,10 +49,11 @@ function getPropertyNode(obj, name) {
 }
 
 /**
- * @param {Expression} node
+ * @param {Expression} targetNode
  * @returns {string[]}
  */
-function getTypes(node) {
+function getTypes(targetNode) {
+  const node = utils.skipTSAsExpression(targetNode)
   if (node.type === 'Identifier') {
     return [node.name]
   } else if (node.type === 'ArrayExpression') {


Test patch:
diff --git a/tests/lib/rules/require-valid-default-prop.js b/tests/lib/rules/require-valid-default-prop.js
index 58adccadf..836f06d5c 100644
--- a/tests/lib/rules/require-valid-default-prop.js
+++ b/tests/lib/rules/require-valid-default-prop.js
@@ -207,6 +207,51 @@ ruleTester.run('require-valid-default-prop', rule, {
         }
       }`,
       parserOptions
+    },
+    {
+      filename: 'test.vue',
+      code: `export default Vue.extend({
+          props: {
+            foo: {
+              type: Array as PropType<string[]>,
+              default: () => []
+            }
+          }
+        });
+      `,
+      parserOptions: { ecmaVersion: 6, sourceType: 'module' },
+      parser: require.resolve('@typescript-eslint/parser'),
+      errors: errorMessage('function')
+    },
+    {
+      filename: 'test.vue',
+      code: `export default Vue.extend({
+          props: {
+            foo: {
+              type: Object as PropType<{ [key: number]: number }>,
+              default: () => {}
+            }
+          }
+        });
+      `,
+      parserOptions: { ecmaVersion: 6, sourceType: 'module' },
+      parser: require.resolve('@typescript-eslint/parser'),
+      errors: errorMessage('function')
+    },
+    {
+      filename: 'test.vue',
+      code: `export default Vue.extend({
+          props: {
+            foo: {
+              type: Function as PropType<() => number>,
+              default: () => 10
+            }
+          }
+        });
+      `,
+      parserOptions: { ecmaVersion: 6, sourceType: 'module' },
+      parser: require.resolve('@typescript-eslint/parser'),
+      errors: errorMessage('function')
     }
   ],
 
@@ -781,6 +826,51 @@ ruleTester.run('require-valid-default-prop', rule, {
       }`,
       parserOptions,
       errors: errorMessage('string')
+    },
+    {
+      filename: 'test.vue',
+      code: `export default Vue.extend({
+          props: {
+            foo: {
+              type: Array as PropType<string[]>,
+              default: []
+            }
+          }
+        });
+      `,
+      parserOptions: { ecmaVersion: 6, sourceType: 'module' },
+      parser: require.resolve('@typescript-eslint/parser'),
+      errors: errorMessage('function')
+    },
+    {
+      filename: 'test.vue',
+      code: `export default Vue.extend({
+          props: {
+            foo: {
+              type: Object as PropType<{ [key: number]: number }>,
+              default: {}
+            }
+          }
+        });
+      `,
+      parserOptions: { ecmaVersion: 6, sourceType: 'module' },
+      parser: require.resolve('@typescript-eslint/parser'),
+      errors: errorMessage('function')
+    },
+    {
+      filename: 'test.vue',
+      code: `export default Vue.extend({
+          props: {
+            foo: {
+              type: Function as PropType<() => number>,
+              default: 10
+            }
+          }
+        });
+      `,
+      parserOptions: { ecmaVersion: 6, sourceType: 'module' },
+      parser: require.resolve('@typescript-eslint/parser'),
+      errors: errorMessage('function')
     }
   ]
 })