无法从只读对象获取嵌套值:TypeScript类型KeysFromParams不符合预期?
问题原因及解决方案
问题根源
你编写的KeysFromParams类型没有触发分布式条件类型,导致逻辑不符合预期。
TypeScript的分布式条件类型仅在条件判断的左侧是裸类型参数(即未被包裹在数组、对象等类型中的单个类型参数)时才会生效。你的写法中,条件左侧是P[number](数组的元素联合类型),并非裸类型参数,因此TypeScript会直接判断整个联合类型是否满足extends BoolParamObj | EnumParam,而不是逐个处理联合类型的成员。
在你的示例中,typeof params的元素联合类型是"hello" | { readonly name: "world"; readonly type: "boolean" },其中包含string类型的"hello",整个联合类型并不属于BoolParamObj | EnumParam的子类型,因此条件判断直接进入else分支,返回的是整个联合类型("hello" | { name: "world"; type: "boolean" })。这就是为什么"world"会被提示不符合类型——它不在返回的联合类型中。
解决方案
你可以通过两种方式修复这个问题:
方式一:使用嵌套条件类型触发分布式处理
将P[number]提取为裸类型参数T,让TypeScript逐个处理联合类型的每个成员:
type KeysFromParams<P extends ParamsArr> = P[number] extends infer T ? T extends BoolParamObj | EnumParam ? T["name"] : T : never
方式二:使用映射类型遍历数组元素
直接遍历数组的每个索引,对每个元素单独判断并提取目标值,最后取所有结果的联合:
type KeysFromParams<P extends readonly any[]> = { [K in keyof P]: P[K] extends string ? P[K] : P[K]["name"] }[number]
验证
修复后,KeysFromParams<typeof params>的结果会是"hello" | "world",此时"world"完全符合类型约束:
const params = [ "hello", { name: "world", type: "boolean" } as const satisfies BoolParamObj ] as const satisfies ParamsArr let key = "world" satisfies KeysFromParams<typeof params> // 无错误
内容的提问来源于stack exchange,提问作者A Kam
相关产品推荐
相关产品推荐

