TypeScript如何定义值为不同强类型函数的字典类型?
解决方案
可以实现需求,核心思路是不要提前给DICT声明统一的索引类型(会覆盖掉每个项的独有类型),而是通过类型约束既保证结构符合要求,又保留每个greeter函数的具体参数、返回值类型。
方案1:TS 4.9及以上版本使用satisfies操作符
satisfies可以在不丢失变量原始类型的前提下,验证变量是否符合指定的类型约束,是当前最优实现:
export enum SomeKeys { FIRST_KEY = 'FIRST_KEY', SECOND_KEY = 'SECOND_KEY', } // 定义字典项的基础约束结构 type DictItemBase = { title: string; greeter: (...args: any[]) => any; } export const DICT = { [SomeKeys.FIRST_KEY]: { title: 'first key title', greeter: (name: string) => ({ name }), }, [SomeKeys.SECOND_KEY]: { title: 'second key title', greeter: (name: string, age: number) => ({ name, age, }), }, // 约束所有枚举key都存在,且结构符合DictItemBase要求 } satisfies Record<SomeKeys, DictItemBase>;
使用时可以正确推导类型:
const { title, greeter } = DICT[SomeKeys.FIRST_KEY]; // greeter自动推导为 (name: string) => { name: string } const { name } = greeter('Adam'); // 无类型报错,返回值属性可正常识别 const { greeter: secondGreeter } = DICT[SomeKeys.SECOND_KEY]; // secondGreeter自动推导为 (name: string, age: number) => { name: string; age: number } const { age } = secondGreeter('Bob', 20); // 正常校验参数数量、类型,识别返回值
方案2:TS 4.9以下版本兼容方案
如果你的TS版本不支持satisfies,可以用泛型函数来实现同样的类型保留效果:
export enum SomeKeys { FIRST_KEY = 'FIRST_KEY', SECOND_KEY = 'SECOND_KEY', } type DictItemBase = { title: string; greeter: (...args: any[]) => any; } // 用泛型函数做类型约束 function defineDict<T extends Record<SomeKeys, DictItemBase>>(dict: T) { return dict; } export const DICT = defineDict({ [SomeKeys.FIRST_KEY]: { title: 'first key title', greeter: (name: string) => ({ name }), }, [SomeKeys.SECOND_KEY]: { title: 'second key title', greeter: (name: string, age: number) => ({ name, age }), }, });
内容的提问来源于stack exchange,提问作者Damian Drozd
相关产品推荐
相关产品推荐

