Skip to content

Type inference fails when using useTemplateRef #5708

@beishuangzz

Description

@beishuangzz

Vue - Official extension or vue-tsc version

3.1.1

VSCode version

1.105.0

Vue version

3.5.14

TypeScript version

5.9.3

System Info

package.json dependencies

Steps to reproduce

Write a composite function

import { ElRadio, ElTableColumn, type ElTable } from 'element-plus'
import { computed, ref, watchEffect, type Ref } from 'vue'

/**
 *
 * @param option
 * @returns
 */
export function useElTableSelectionColumn<T>(
    option:
        | {
              multiple: true
              checkedList?: T[]
              tableRef: Ref<InstanceType<typeof ElTable> | null>
          }
        | {
              multiple?: false
              rowKey?: string | ((item: T) => string)
          }
) {
    if (option.multiple) {
        let { checkedList, tableRef } = option
        let table = tableRef
        let selection = ref<any[]>([])
        watchEffect(() => {
            if (table.value) {
                selection.value = table.value.store.states.selection.value
                if (checkedList) {
                    selection.value!.push(...checkedList)
                }
            }
        })

        let selectionColumn = () => {
            return (
                <>
                    <ElTableColumn type="selection" reserve-selection={true} fixed="left" width={55} />
                </>
            )
        }
        return {
            selection,
            selectionColumn: selectionColumn
        }
    } else {
        let { rowKey = 'objectid', multiple } = option
        let checkedRow = ref<T>()
        let checkedId = ref('')
        /**
         * 获取选项label
         * @param item
         */
        const getLabel = (item: T): string => {
            if (typeof rowKey === 'function') {
                return rowKey(item)
            } else {
                return item[rowKey]
            }
        }
        let selectionColumn = () => {
            return (
                <>
                    <ElTableColumn fixed="left" width={55} label={'选择'}>
                        {{
                            default: ({ row, $index }) => {
                                return (
                                    <>
                                        <ElRadio
                                            modelValue={checkedId.value}
                                            label={getLabel(row)}
                                            onUpdate:modelValue={(value) => {
                                                checkedId.value = value as string
                                                checkedRow.value = row
                                            }}
                                        >
                                            <span></span>
                                        </ElRadio>
                                    </>
                                )
                            }
                        }}
                    </ElTableColumn>
                </>
            )
        }

        let checkedRows = computed<T[]>(() => {
            if (checkedRow.value) {
                return [checkedRow.value] as T[]
            }
            return []
        })
        return {
            selectionColumn: selectionColumn,
            selection: checkedRows
        }
    }
}

Use this function in a Vue component.

<script setup lang="ts">
import { ElTable } from 'element-plus'
import { ref, useTemplateRef } from 'vue'
import { useElTableSelectionColumn, useElTableSelectionColumn2 } from './useList'

let tableRef = useTemplateRef('tableRef') //使用useTemplateRef导致当前组件template类型和错误提示失效, 但使用ref就没有问题
// let tableRef = ref<InstanceType<typeof ElTable> | null>(null)

let { selection, selectionColumn } = useElTableSelectionColumn<any>({
    tableRef,
    multiple: true
})

//不使用泛型时也可以正常运行
// let { selection, selectionColumn } = useElTableSelectionColumn2({
//     tableRef,
//     multiple: true
// })

// let { selection, selectionColumn } = useSelectionColumn({tableRef, multiple: true})

let data = [
    {
        name: 'ddddddd',
        id: '1'
    }
]

</script>

<template>
    <div>
        <el-table ref="tableRef" row-key="id" :data="data">
            <selectionColumn />
            <el-table-column label="序号" v-slot="data" width="80">
                {{ data.$index + 1 }}
            </el-table-column>
            <el-table-column label="名称" prop="name" show-overflow-tooltip min-width="150" />
        </el-table>
    </div>
</template>

<style scoped lang="less"></style>
<style lang="less"></style>

At this point, the type hints in the Vue component's template are not working.

What is expected?

Resolve type hinting issues

What is actually happening?

Type inference fails

Link to minimal reproduction

https://github.com/beishuangzz/vue_test

Any additional comments?

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions