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

如何实现API相同但参数选项不同的TypeScript策略对象?

问题描述

我在使用TypeScript泛型时遇到了编译器校验问题,想通过JavaScript对象实现策略模式选择器——每个策略共享统一API,但execute方法的参数类型随策略不同而变化。

现有代码如下:

enum Strategy {
    One,
    Two,
    ...
}

export interface StrategiesApi<TOptions> {
    delete(): void;
    execute(options: TOptions): void;
}

export type Strategies<TOptions> = {
    [key in Strategy]: StrategiesApi<TOptions>;
};


const strategies = {
    [Strategy.One]: {
        delete: strategyOneDelete,
        execute: strategyOneExecute,
        ...
    },
    [Strategy.Two]: {
        delete: strategyTwoDelete,
        execute: strategyTwoExecute,
        ...
    },
};

编写策略选择函数时:

export const getStrategy = <TOptions>(strategy: Strategy): StrategyApi<TOptions> => {
    const strategy = strategies[strategy];

    if (!strategy) {
        throw new Error('Strategy not found');
    }

    return strategy;
};

TypeScript报错,提示TOptions无法匹配对应策略execute方法的参数类型。用类型断言return strategy as StrategyApi<TOptions>能绕过错误,但会丢失类型校验能力。

需求是:实现带泛型参数的策略模式选择器,避免完全显式声明返回类型,也不想手动编写每个策略的完整接口定义。

解决方案

核心是利用TypeScript的自动类型推导和索引类型关联,让策略与对应参数类型自动绑定,无需手动维护统一泛型或冗长接口。

1. 定义各策略的参数类型

先明确每个策略对应的execute参数结构:

// 策略One的参数类型
type StrategyOneOptions = {
  id: string; // 自定义参数字段
};

// 策略Two的参数类型
type StrategyTwoOptions = {
  count: number; // 自定义参数字段
};

2. 实现具体策略并让TS自动推导类型

先写好每个策略的具体方法,再组合成策略对象,TypeScript会自动推导每个策略的完整类型:

// 策略One的具体实现
const strategyOneDelete = () => {
  // 业务逻辑代码
};
const strategyOneExecute = (options: StrategyOneOptions) => {
  // 业务逻辑代码
};

// 策略Two的具体实现
const strategyTwoDelete = () => {
  // 业务逻辑代码
};
const strategyTwoExecute = (options: StrategyTwoOptions) => {
  // 业务逻辑代码
};

// 组合策略对象,TS自动推导每个属性的类型
const strategies = {
    [Strategy.One]: {
        delete: strategyOneDelete,
        execute: strategyOneExecute,
    },
    [Strategy.Two]: {
        delete: strategyTwoDelete,
        execute: strategyTwoExecute,
    },
};

3. 编写类型关联的策略选择函数

通过索引类型查询提取策略对象的类型,让函数返回类型与传入的Strategy枚举值强关联:

// 提取自动推导的策略映射类型
type StrategyMap = typeof strategies;

// 定义选择函数,泛型约束为Strategy枚举,返回对应策略的类型
export const getStrategy = <S extends Strategy>(strategy: S): StrategyMap[S] => {
    const selectedStrategy = strategies[strategy];

    if (!selectedStrategy) {
        throw new Error('Strategy not found');
    }

    return selectedStrategy;
};

4. 使用效果

调用getStrategy时,TypeScript会自动根据传入的枚举值,推导对应策略的execute参数类型,保留完整的类型校验:

// 自动识别execute参数为StrategyOneOptions
const strategyOne = getStrategy(Strategy.One);
strategyOne.execute({ id: "123" }); // 类型正确
strategyOne.execute({ count: 10 }); // 类型报错,符合预期

// 自动识别execute参数为StrategyTwoOptions
const strategyTwo = getStrategy(Strategy.Two);
strategyTwo.execute({ count: 10 }); // 类型正确
strategyTwo.execute({ id: "123" }); // 类型报错,符合预期

内容的提问来源于stack exchange,提问作者Dez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 10:40:25