Vue.js具名插槽结合TypeScript的元组类型推断问题
Vue具名插槽与元组类型推断问题
Vue.js的具名插槽特性可用于覆盖指定插槽的默认渲染内容,组件内的实现方式如下:
<td v-for="(column, index) in tuple"> <slot :name="slotName(column)" // string :value="getValue(item, column) as TupleValues<typeof tuple, typeof item>[index] </slot> </td>
在使用该组件时,可通过具名插槽自定义指定列的渲染:
<template #score="{ value }"> // value 应为 TupleMap<typeof tuple, typeof item>['score'] // score 是此前 slotName(column) 返回的插槽名 </template>
这是一种自定义指定插槽默认渲染内容的模式:columns是一个元组,用于定义表格的每一列,以及从数组项中获取对应值的键(该元组也可定义返回列自定义值的函数);数组中的每个元素代表一行数据。
元组值类型的类型定义
我们可以通过以下两个类型来获取每个元组元素的值类型:
TupleValues
type TupleValues< T extends Array<{ key: keyof U | string; value?: keyof U | string | ((...args: any[]) => any) }>, U > = { [P in keyof T]: T[P]['key'] extends keyof U ? U[T[P]['key']] : T[P]['value'] extends keyof U ? U[T[P]['value']] : T[P]['value'] extends (...args: unknown[]) => unknown ? ReturnType<T[P]['value']> : never }
TupleMap
type TupleMap< T extends Array<{ key: keyof U | string; value?: keyof U | string | ((...args: any[]) => any) }>, U > = { [P in T[number] as P['key']]: P['key'] extends keyof U ? U[P['key']] : P['value'] extends keyof U ? U[P['value']] : P['value'] extends (...args: unknown[]) => unknown ? ReturnType<P['value']> : never }
存在的问题
遗憾的是,使用v-for循环渲染插槽时,上述类型推断会失效。
如果不使用v-for,而是为每个元组索引手动定义插槽,虽然能从元组中推断出确切的插槽名和值类型,但这种方式无法适配任意数量的列:
<td> <slot :name="columnName(columns[0])" // 可从元组推断出确切的插槽名 :value="getValue(item, column) as TupleValues<typeof tuple, typeof item>[0]" // 可从元组推断出确切的插槽值 > <DefaultSlotRenderer /> </slot> </td> <td> <slot :name="columnName(columns[1])" // 可从元组推断出确切的插槽名 :value="getValue(item, column) as TupleValues<typeof tuple, typeof item>[1]" // 可从元组推断出确切的插槽值 > <DefaultSlotRenderer /> </slot> </td> <td> <slot :name="columnName(columns[2])" // 可从元组推断出确切的插槽名 :value="getValue(item, column) as TupleValues<typeof tuple, typeof item>[2]" // 可从元组推断出确切的插槽值 > <DefaultSlotRenderer /> </slot> </td>
补充说明
事实证明,即使不使用v-for循环,该方案也无法生效,且问题并非出在类型定义上。建议将代码复制到本地运行以查看智能提示效果。
内容的提问来源于stack exchange,提问作者darkbasic
相关产品推荐
相关产品推荐

