Nuxt UI 4.4 的 USelectMenu 不接受 id,检查 GetItemKeys 类型修正
Nuxt UI 4.4.0 的复杂选项类型可能让合法 value-key 与 v-model 误报。核对 4.5.0 的可空成员及 DotPathKeys 修正,保留 branded ID 契约。
USelectMenu 的选项对象明明有 id,value-key="id" 却报不能赋给 GetItemKeys,连 v-model 的值类型也跟着失配。若项目使用 Nuxt UI 4.4.0,选项中带有 branded ID 或较复杂的成员类型,可以检查组件的键名推导。
Type '"id"' is not assignable to type 'GetItemKeys<...>'.
这类错误不一定表示属性拼错。Nuxt UI 4.5.0 包含两项相关类型修正:普通选项类型中的可空、可选成员支持,以及 branded 类型和 Date、Map 等复杂成员的点路径递归边界。两者不能混成一个“所有泛型都坏了”的结论。
保留项目原来的 ID 契约
下面的形状用于说明 branded ID 与组件键名的关系,放在已经配置 Nuxt UI 的 Vue 单文件组件中。数组先留空,业务数据仍应由项目原来的校验和转换入口提供:
<script setup lang="ts">
import { ref } from "vue";
type BrandId = number & { readonly __brand: "BrandId" };
interface BrandOption {
id: BrandId;
name: string;
}
const items = ref<BrandOption[]>([]);
const selected = ref<BrandId>();
</script>
<template>
<USelectMenu
v-model="selected"
:items="items"
value-key="id"
label-key="name"
/>
</template>
branded 类型用来区分形状相同、业务含义不同的 ID。为了让组件通过检查就把它全改成普通 number,可能让本来不允许混用的编号互相赋值。把整组 items 或组件断言为 any,也会同时丢掉真实键名错误的保护。
先核对实际选项接口确实包含 id、name,value-key 指向的是希望写入模型的字段。若模型原本应保存整个对象,就不能继续按保存 ID 的契约配置,升级类型工具也不会替应用决定这件事。
复杂成员不应被一路展开成点路径
受影响的类型工具会递归生成嵌套对象的点路径。branded 基础类型或 Date 等成员不应像普通记录一样无限向内部展开,否则本来简单的键名联合也可能受到干扰。
已核对的正式 4.5.0 使用更明确的普通对象判断,排除基础类型、函数、数组及若干内置复杂对象,并调整 GetItemKeys 的字符串键约束。它保留真正嵌套普通对象的路径支持,没有要求业务自行复制一套 _FlatItem 补丁。
按框架和组件库的兼容范围更新依赖,确认锁文件及实际安装的 Nuxt UI 版本。4.5.0 是已核对包含修正的发行节点,不代表后续版本不需要再对照自己的变更记录。
重新执行原来的 vue-tsc 或 Nuxt 类型检查,既要确认合法键不再误报,也要确认故意写错的键仍被拒绝。再用实际选项选择和清空一次,检查模型保存的是预期 ID 还是对象、空值类型是否符合约定。类型修正不会自动验证服务器返回的数据,也不会改变运行时选择器的值契约。


