TypeScript条件联合类型失效:'string'无法赋值给'never'报错排查
问题原因及解决方法:Type 'string' is not assignable to type 'never'
问题场景
定义了用于推导对象指定路径属性类型的GetFieldType条件类型,以及基于它的Route类型,但使用Route<Item>时出现类型错误:Type 'string' is not assignable to type 'never'.ts(2322)。代码如下:
type GetFieldType<TObject, TPath> = TPath extends keyof TObject ? TObject[TPath] : undefined; type Route<TObject> = { [TPath in string]: Extract<GetFieldType<TObject, TPath>, boolean | number | string>; }; interface Item { foo: string } const r: Route<Item> = { "foo": "string" // 报错:Type 'string' is not assignable to type 'never'.(2322) }
问题原因
- Route类型的键遍历范围错误:
[TPath in string]表示遍历所有string类型的键,而非目标对象TObject的键集合。 - 条件类型的泛型推断失效:当
TPath是任意string时,TypeScript无法将具体的键(比如"foo")与泛型参数TPath关联。对于绝大多数string类型的键(非TObject的键),GetFieldType返回undefined,经过Extract处理后得到never;即使是TObject的键,由于TPath是任意string而非具体的keyof TObject,TypeScript也无法推断出正确的属性类型,最终整个Route<TObject>的所有属性类型都被推断为never,导致赋值时类型不匹配。
解决方法
方法一:限制Route的键为目标对象的键集合
如果只需要支持目标对象的一级键,直接将Route的键遍历范围改为keyof TObject,这样每个键对应的类型会被正确推断:
type GetFieldType<TObject, TPath> = TPath extends keyof TObject ? TObject[TPath] : undefined; // 遍历keyof TObject而非所有string type Route<TObject> = { [TPath in keyof TObject]: Extract<GetFieldType<TObject, TPath>, boolean | number | string>; }; interface Item { foo: string } const r: Route<Item> = { "foo": "string" // 类型匹配,无报错 }
方法二:支持嵌套路径的扩展(可选)
如果需要支持嵌套属性路径(比如"foo.bar"),需要修改GetFieldType来处理路径拆分,同时调整Route的键类型为合法的路径字符串:
// 处理嵌套路径的GetFieldType type GetFieldType<TObject, TPath extends string> = TPath extends `${infer K}.${infer Rest}` ? K extends keyof TObject ? GetFieldType<TObject[K], Rest> : undefined : TPath extends keyof TObject ? TObject[TPath] : undefined; // 定义合法路径类型(这里简化为string,可根据需要限制为TObject的所有可能路径) type Route<TObject> = { [TPath in string]: Extract<GetFieldType<TObject, TPath>, boolean | number | string>; }; interface Item { foo: string; bar: { baz: number; }; } const r: Route<Item> = { "foo": "string", // 正确 "bar.baz": 123 // 正确 }
注意:方法二中Route的键仍为string,但TypeScript在具体赋值时会根据GetFieldType推断对应类型,不过这种方式无法在编译阶段限制键必须是合法路径,若需要严格限制路径,可进一步实现Paths类型来生成所有合法路径集合。
内容的提问来源于stack exchange,提问作者striderhobbit
相关产品推荐
相关产品推荐

