如何从注册表对象的关联键中推断对应函数的特定返回类型?
解决TypeScript注册表函数返回类型收窄问题
首先,你的问题本质是TypeScript泛型函数内部无法自动将registry[T]()的调用结果收窄为对应键的具体返回类型——因为泛型参数T是keyof typeof registry的子集,而非具体的字面量类型,TS无法在函数内部追踪T的具体值,因此会推断出所有返回类型的联合。
更简洁的实现方式
你可以直接利用TypeScript内置的ReturnType工具类型(无需自己定义),并简化函数体:
// 仅可从此处开始修改 const registryEater = <T extends keyof typeof registry>(registryKey: T): ReturnType<typeof registry[T]> => { return registry[registryKey]() as ReturnType<typeof registry[T]>; }; // 仅可修改至此处
如果追求极致简洁,还可以写成一行箭头函数:
const registryEater = <T extends keyof typeof registry>(k: T) => registry[k]() as ReturnType<typeof registry[T]>;
为什么必须用类型断言?
目前TypeScript没有办法在不使用类型断言的情况下,让编译器自动将泛型索引的函数调用结果精确关联到对应键的返回类型。因为泛型T在函数内部是一个“范围”而非具体值,编译器无法确定registry[T]()的具体返回类型,只能推断为所有可能类型的联合。类型断言是告诉编译器“我比你更清楚这个值的类型”,这是当前最直接且符合你“无需修改函数即可新增注册表条目”需求的方案。
额外优化:预定义注册表返回类型映射(可选)
如果你想让类型定义更清晰,可以预先定义注册表的返回类型映射,这样函数返回类型的可读性更好:
// 仅可从此处开始修改 type RegistryReturns = { [K in keyof typeof registry]: ReturnType<typeof registry[K]>; }; const registryEater = <T extends keyof typeof registry>(registryKey: T): RegistryReturns[T] => { return registry[registryKey]() as RegistryReturns[T]; }; // 仅可修改至此处
这种方式同样不需要在新增注册表条目时修改函数,只是多了一层类型映射的定义,适合需要更明确类型别名的场景。
内容的提问来源于stack exchange,提问作者Václav Pruner
相关产品推荐
相关产品推荐

