TypeScript:能否基于对象其他属性值限定当前属性的字面量联合类型
在TypeScript中能否让对象属性的字面量联合类型依赖同一对象的另一属性?
需求是让对象的subKey属性允许的字面量联合类型,根据同一对象的baseKey属性值动态确定,本质是在类型中关联当前实例的属性类型。
需求伪代码示例
type TMethodKeys<T> = { [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never; }[keyof T]; type OptionA = { aFunctionForOptionA: () => string; anotherFunctionForOptionA: () => number; } type OptionB = { thisIsAFunctionForOptionB: () => boolean; thisIsAnotherFunctionForOptionB: () => bigint; } type Base = { baseFunctionA: () => OptionA; baseFunctionB: () => OptionB; } // 期望subKey的类型依赖当前实例的baseKey值,但当前写法无法实现关联 type Objective = { baseKey: TMethodKeys<Base>; subKey: TMethodKeys<ReturnType<Base[Objective['baseKey']]>>; } const Test = [ { baseKey: 'baseFunctionA', subKey: '...' as never, // 期望允许:'aFunctionForOptionA' | 'anotherFunctionForOptionA' }, { baseKey: 'baseFunctionB', subKey: '...' as never, // 期望允许:'thisIsAFunctionForOptionB' | 'thisIsAnotherFunctionForOptionB' }, ] as const satisfies Objective[];
参考案例:Document.addEventListener
类似Document接口中addEventListener的设计,回调的ev参数类型会根据type参数的值动态匹配:
interface Document { addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; }
解决方案:通过泛型参数关联属性类型
要实现属性间的类型依赖,需给Objective添加泛型参数,用该参数捕获baseKey的具体类型,进而推导subKey的合法值范围。
正确的类型定义
type TMethodKeys<T> = { [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never; }[keyof T]; type OptionA = { aFunctionForOptionA: () => string; anotherFunctionForOptionA: () => number; } type OptionB = { thisIsAFunctionForOptionB: () => boolean; thisIsAnotherFunctionForOptionB: () => bigint; } type Base = { baseFunctionA: () => OptionA; baseFunctionB: () => OptionB; } // 泛型K约束baseKey的类型,subKey基于K动态推导 type Objective<K extends TMethodKeys<Base>> = { baseKey: K; subKey: TMethodKeys<ReturnType<Base[K]>>; } // 生成包含所有可能场景的联合类型 type AllObjectives = Objective<TMethodKeys<Base>>;
验证代码
此时编写Test数组时,TypeScript会自动校验每个对象的subKey是否符合对应baseKey的类型约束:
const Test = [ { baseKey: 'baseFunctionA', subKey: 'aFunctionForOptionA', // 合法,无报错 }, { baseKey: 'baseFunctionB', subKey: 'thisIsAnotherFunctionForOptionB', // 合法,无报错 // subKey: 'aFunctionForOptionA' // 此处会报错:类型不匹配 }, ] as const satisfies AllObjectives[];
原理说明
这种实现和addEventListener的设计逻辑一致:
- 用泛型参数捕获
baseKey的具体类型(对应addEventListener中的K) - 基于该泛型参数推导
subKey的合法类型(对应DocumentEventMap[K]的动态匹配) - 通过
AllObjectives联合类型覆盖所有可能的baseKey场景,确保数组中每个元素都能获得精准的类型校验
内容的提问来源于stack exchange,提问作者degebine
相关产品推荐
相关产品推荐

