如何在将对象转为接口类型后获取原始嵌套对象类型?
解决TypeScript中指定接口后丢失原始嵌套键类型的问题
问题分析
当把具有具体嵌套结构的对象赋值给带字符串索引签名的Routing接口后,TypeScript会擦除对象的具体类型信息,仅保留接口定义的宽泛类型。这导致NestedKeyOf工具类型无法解析出原始的具体嵌套键联合类型,只能返回string。
解决方案
方法1:通过泛型函数约束类型并保留原始结构
不直接给变量指定Routing类型,而是用泛型函数验证对象是否符合Routing结构,同时保留原始对象的具体类型:
interface Routing { [SEGMENT: string]: Routing | number | string; } // 泛型函数,约束对象符合Routing结构,同时保留原始类型 function createRouting<T extends Routing>(route: T): T { return route; } const exampleRoutes2 = createRouting({ api: { products: "myProductEndpoint", customers: "myCustomerEndpoint", }, }); // type test2 = "api" | "api.products" | "api.customers" type test2 = NestedKeyOf<typeof exampleRoutes2>;
泛型T会捕获原始对象的具体类型,T extends Routing确保对象符合接口要求,既完成类型校验,又保留了原始嵌套键信息。
方法2:使用as const结合泛型约束(适用于字面量对象)
如果对象是字面量形式,用as const强制保留字面量类型,再通过泛型验证其符合Routing结构:
interface Routing { [SEGMENT: string]: Routing | number | string; } const exampleRoutes = { api: { products: "myProductEndpoint", customers: "myCustomerEndpoint", }, } as const; // 泛型类型,验证T是否符合Routing结构 type EnsureRouting<T> = T extends Routing ? T : never; const exampleRoutes2: EnsureRouting<typeof exampleRoutes> = exampleRoutes; // type test2 = "api" | "api.products" | "api.customers" type test2 = NestedKeyOf<typeof exampleRoutes2>;
as const让TypeScript将对象的属性值和键都视为字面量类型,EnsureRouting泛型则用于验证该类型是否符合Routing结构,避免直接赋值导致的类型擦除。
方法3:将Routing改为泛型接口
把原本的索引签名接口改成泛型版本,让它可以接受具体的键类型,从而保留嵌套结构的类型信息:
// 泛型版本的Routing接口 type Routing<T extends Record<string, any>> = { [K in keyof T]: T[K] extends object ? Routing<T[K]> : T[K]; }; const exampleRoutes = { api: { products: "myProductEndpoint", customers: "myCustomerEndpoint", }, }; // 推导具体的Routing类型 type ExampleRouting = Routing<typeof exampleRoutes>; const exampleRoutes2: ExampleRouting = exampleRoutes; // type test2 = "api" | "api.products" | "api.customers" type test2 = NestedKeyOf<typeof exampleRoutes2>;
泛型T捕获具体的对象结构,Routing类型会递归适配嵌套对象的结构,既保留原始类型信息,又完成结构约束。
核心原理
问题的根源在于字符串索引签名会擦除具体的键类型信息,导致TypeScript无法识别对象的具体嵌套键。上述方案的核心都是通过泛型或as const保留原始对象的具体类型,同时确保对象符合Routing的结构要求,避免类型擦除。
内容的提问来源于stack exchange,提问作者Harkan
相关产品推荐
相关产品推荐

