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

TypeScript中多函数通用参数的优雅处理方案问询

多引擎游戏函数的参数一致性实现方案探讨

我正在开发一款游戏,需要针对不同引擎实现功能等效的函数,且确保这些函数使用相同的默认参数。以下是我尝试的几种实现方式及其不足之处:

蛮力法

function frobnicateA(req: number, opt: number = 5) {
    console.log(req, opt)
}

frobnicateA(1, 2)

function frobnicateB(req: number, opt: number = 5) {
    console.log(req, opt)
}

frobnicateB(1, 2)
  • 调用时参数未命名,可读性差
  • 不同实现间参数名无一致性强制,易出现差异
  • 默认参数重复定义,维护成本高

常规法

(frobnicateB的实现类似,后续不再赘述)

interface Config {
    req: number
    opt?: number
}

function frobnicateA(cfg: Config) {
    let opt = cfg.opt ?? 5
    console.log(cfg.req, opt)
}

frobnicateA({ req: 1, opt: 2 })
  • 可选参数较多时,样板代码冗余
  • 默认参数在各实现中重复定义
  • 实现时可能遗漏参数默认值填充,导致逻辑错误

ES风格法

interface Config {
    req: number
    opt?: number
}

function frobnicateA({ req, opt = 5 }: Config) {
    console.log(req, opt)
}

frobnicateA({ req: 1, opt: 2 })
  • 默认参数在各实现中重复定义,维护不便
  • 遗漏默认参数赋值时,TypeScript无提示

接近理想法

interface Config {
    req: number
    opt?: number
}
const defaultOpt = 5

function frobnicateA({ req, opt = defaultOpt }: Config) {
    console.log(req, opt)
}

frobnicateA({ req: 1, opt: 2 })
  • 遗漏默认参数赋值时无提示
  • 写法不够简洁优雅

类封装法

class Config {
    req1!: number
    req2!: number
    opt: number = 5
    constructor(cfg: Pick<Config, 'req1' | 'req2'> & Partial<Config>) {
        Object.assign(this, cfg)
    }
}

function frobnicateA(cfg: Config) {
    console.log(cfg.req1, cfg.req2, cfg.opt)
}

frobnicateA(new Config({ req1: 1, req2: 2, opt: 3 }))
  • 构造函数设计晦涩,可读性差
  • Pick中重复声明必填参数,无强制校验机制
  • 函数调用需额外实例化Config,操作繁琐

技巧法

type RequiredKeys<T> = {
    [K in keyof T]: T[K] extends Required<T>[K] ? K : never;
}[keyof T];

type FillsAndOverrides<T> = Pick<T, RequiredKeys<T>> & Partial<T>;

class Config{
    req!: number
    opt?: number = 5
    constructor(cfg: FillsAndOverrides<Config>){
        Object.assign(this, cfg)
    }
}

function frobnicateA(cfg: Config){
    console.log(cfg.req, cfg.opt)
}

frobnicateA(new Config({req:1, opt:2}))
  • 函数调用需额外实例化Config,操作繁琐
  • 滥用?作为RequiredKeys的筛选标记,逻辑不直观
  • 直接调用frobnicateA({ req: 1 })时无报错提示

填充函数法

interface Config {
    req: number
    opt?: number
}

function fillConfig(cfg: Config): Required<Config> {
    return { ...{ opt: 5 }, ...cfg };
}

function frobnicateA(cfg: Config) {
    let fullCfg = fillConfig(cfg)
    console.log(fullCfg.req, fullCfg.opt)
}

frobnicateA({ req: 1, opt: 2 })
  • 默认参数定义在填充函数中,位置隐蔽,不易查找
  • 实现时遗漏调用fillConfig,TypeScript无警告

调用端填充函数法

interface Config {
    req: number
    opt?: number
}

function fillConfig(cfg: Config): Required<Config> {
    return { ...{ opt: 5 }, ...cfg };
}

function frobnicateA(cfg: Required<Config>) {
    console.log(cfg.req, cfg.opt)
}

frobnicateA(fillConfig({ req: 1, opt: 2 }))
  • 默认参数定义位置隐蔽
  • 参数填充逻辑应由函数自身完成,而非调用端处理

理想但不可行方案

parameters Config {
    req: number
    opt: number = 5
}

function frobnicateA({req, opt}: Config) {
    console.log(req, opt)
}

frobnicateA({ req: 1, opt: 2 })

我知道有些要求过于挑剔,最终也可以选择上述任一方案,但总觉得应该存在一种更优雅、无上述问题的解决方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 12:41:00