Skip to content

Invalid inferred any type when using useTemplateRef #285

@DesselBane

Description

@DesselBane

Before You File a Bug Report Please Confirm You Have Done The Following...

  • I'm using eslint-plugin-vue.
  • I'm sure the problem is a parser problem. (If you are not sure, search for the issue in eslint-plugin-vue repo and open the issue in eslint-plugin-vue repo if there is no solution.
  • I have tried restarting my IDE and the issue persists.
  • I have updated to the latest version of the packages.

What version of ESLint are you using?

9.39.2

What version of eslint-plugin-vue and vue-eslint-parser are you using?

  • "eslint-plugin-vue": "10.6.2"
  • "vue-eslint-parser": "10.2.0"

Other versions

  • "@types/node": "24.10.4"
  • "@eslint/js": "9.39.2"
  • "@vue/eslint-config-typescript": "14.6.0"
  • "eslint": "9.39.2"
  • "eslint-import-resolver-typescript": "4.4.4"
  • "jiti": "2.6.1"
  • "prettier": "3.8.1"
  • "typescript": "5.9.3"
  • "typescript-eslint": "8.50.0"

What did you do?

Configuration
import { defineConfig } from 'eslint/config'
import eslint from '@eslint/js'
import {
  configureVueProject,
  defineConfigWithVueTs,
  vueTsConfigs,
} from '@vue/eslint-config-typescript'
import pluginVue from 'eslint-plugin-vue'

function createEslintConfig() {
  const projectServiceConfig = {
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
  }

  configureVueProject({
    tsSyntaxInTemplates: true,
    rootDir: import.meta.dirname,
  })

  return defineConfig(
    eslint.configs.recommended,
    // @ts-expect-error - This is a valid config, but the types are currently wrong
    ...defineConfigWithVueTs(
      projectServiceConfig,
      pluginVue.configs['flat/recommended'],
      vueTsConfigs.stylisticTypeChecked,
      vueTsConfigs.strictTypeChecked,
    ),
  )
}

export default createEslintConfig()
<script setup lang="ts">
import { computed, useTemplateRef } from 'vue'

const someOtherName = useTemplateRef('someElement')

const doubleHeight = computed(() => {
  const height = someOtherName.value?.clientHeight ?? 0
  return height + height
})

</script>
<template>
  <div ref="someElement">
    Hi there! My double height is {{ doubleHeight }}px.
  </div>
</template>

What did you expect to happen?

That the height variable inside the doubleHeight computed is of type number

What actually happened?

The height variable inside the doubleHeight computed is detected as type any which triggers an error from the @typescript-eslint/restrict-plus-operands (though any rule with type information might be a problem here)

Link to Minimal Reproducible Example

https://github.com/DesselBane/repro-vue-eslint-any

Additional comments

Possible workaround is to explicitly specify the type of the template ref like this

<script setup lang="ts">
import { computed, useTemplateRef, type TemplateRef } from 'vue'

const someOtherName: TemplateRef<HTMLDivElement> = useTemplateRef('someElement')

const doubleHeight = computed(() => {
  const height = someOtherName.value?.clientHeight ?? 0
  return height + height
})

</script>
<template>
  <div ref="someElement">
    Hi there! My double height is {{ doubleHeight }}px.
  </div>
</template>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions