TypeScript泛型场景中无法索引T0类型的TS2536问题排查
TypeScript类型代码报错原因及解决
为什么第一段代码会报错?
T 被约束为 T1 的子类型,但TypeScript允许子类型包含超类型没有的额外属性。比如你可以定义 type Test = {key1: string, key2: string, key3: string},它完全符合 T extends T1 的约束,但 key3 并不是 T0 的键。这时候 keyof T 就可能包含 T0 不存在的键,用 k 去索引 T0 自然会触发报错——TypeScript没法保证 k 一定是 T0 的合法键。
为什么你尝试的第二段代码还是报错?
你用 as k extends keyof T0 ? k : never 过滤掉了非 T0 的键,但TypeScript的类型推断在这里没同步更新:它依然把 k 当成 keyof T 类型,没法自动识别经过过滤后的 k 已经是 keyof T0 的子集,所以 T0[k] 还是会报错。
解决方法
方法一:添加类型断言
直接断言 k 是 keyof T0,明确告诉TypeScript过滤后的 k 肯定能索引 T0:
interface T0 { key1: string key2: string } type T1 = { [v in keyof T0]: string } type T2<T extends T1> = { [k in keyof T as k extends keyof T0 ? k : never]: T0[k as keyof T0] }
方法二:严格约束T的键范围
如果不需要 T 包含额外属性,可以把 T 的约束改成只能包含 T0 的键,这样 keyof T 就必然是 T0 的合法键:
interface T0 { key1: string key2: string } type T1 = { [v in keyof T0]: string } type T2<T extends Record<keyof T0, string>> = { [k in keyof T]: T0[k] }
方法三:直接基于T0的键映射
如果你的需求是把 T 中属于 T0 的键的类型替换为 T0 的类型,同时保留额外属性,可以直接遍历 keyof T0,再结合 Omit 保留额外属性:
interface T0 { key1: string key2: string } type T1 = { [v in keyof T0]: string } type T2<T extends T1> = { [k in keyof T0]: T0[k] } & Omit<T, keyof T0>
内容的提问来源于stack exchange,提问作者Tony
相关产品推荐
相关产品推荐

