You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 14:48:17