如何让TypeScript的keyof typeof返回具体键并避免循环引用
解决方案:保留Route约束同时提取具体键类型
问题根源
直接给routes变量指定Routes = Record<string, Route>类型时,TypeScript会自动将对象键的类型拓宽为string,而非具体的字面量值;而尝试用Record<keyof typeof routes, Route>定义Routes会触发循环引用错误,因为typeof routes依赖Routes类型,反之亦然。
方案一:使用satisfies关键字(TypeScript 4.9+ 推荐)
satisfies关键字可以让对象满足指定类型约束,同时保留自身的字面量类型信息,完美解决类型拓宽和约束的矛盾。
type Route = { url: string auth: boolean } // 让对象满足Record<string, Route>约束,同时保留键的字面量类型 const routes = { add: { url: '/comment', auth: false }, delete: { url: '/comment', auth: true } } satisfies Record<string, Route> // 提取具体键类型:'add' | 'delete' type RouteKeys = keyof typeof routes // 提取完整的Routes类型(包含具体键和Route结构) type Routes = typeof routes
方案二:泛型函数约束(兼容低版本TypeScript)
如果项目使用的TypeScript版本低于4.9,可以通过泛型函数来实现约束,同时保留字面量类型。
type Route = { url: string auth: boolean } // 泛型函数约束输入对象必须符合Record<string, Route>结构,同时返回原类型 function createRoutes<T extends Record<string, Route>>(routes: T) { return routes } // 调用函数时传入对象,自动保留键的字面量类型 const routes = createRoutes({ add: { url: '/comment', auth: false }, delete: { url: '/comment', auth: true } }) // 提取具体键类型:'add' | 'delete' type RouteKeys = keyof typeof routes // 提取完整的Routes类型 type Routes = typeof routes
内容的提问来源于stack exchange,提问作者Greg Wozniak
相关产品推荐
相关产品推荐

