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

能否基于函数参数生成静态类型对象?TypeScript技术问询

基于动态字符串参数构建带Intellisense的静态类型Params对象

我原本以为这没法实现,但还是想确认一下。我尝试通过函数传入的字符串参数,为Intellisense创建一个静态类型的params对象,当前代码如下:

type Query = {
    _def: {
        params: Record<string, string> // 这里该怎么写?
    }
    params: (name: string) => Query;
}

const queryBuilder = (def: Query["_def"]): Query => {
    return {
        _def: def,
        params: (name) => {
            const innerDef = {
                ...def,
                params: {
                    ...def.params,
                    [name]: undefined as unknown as string // 这里只是用来保存类型
                }
            }
            return queryBuilder(innerDef);
        }
    }
}

const c = queryBuilder({} as Query["_def"]);
const d = c.params("hello").params("world");
d._def.params; // 希望Intellisense能提示hello和world
const e: typeof c._def.params = {} // 希望抛出错误,提示hello和world是必填项

目前用Record<string, string>无法提供Intellisense提示或错误提示,也没法用const断言,因为没有可断言的具体内容。有没有其他可行的方法?


解决方案

要实现动态累积参数名并生成静态类型,需要让Query和queryBuilder支持泛型,用泛型追踪已添加的参数名称:

// 用泛型P追踪已添加的参数名集合,默认是空集合
type Query<P extends string = never> = {
    _def: {
        // 映射类型:P中的每个字符串都是必填的string类型键
        params: { [K in P]: string }
    }
    // params方法接收新参数名N,返回包含P|N集合的新Query类型
    params: <N extends string>(name: N) => Query<P | N>;
}

// 构建函数用泛型P约束参数和返回值类型
const queryBuilder = <P extends string = never>(def: Query<P>["_def"]): Query<P> => {
    return {
        _def: def,
        params: (name) => {
            const innerDef = {
                ...def,
                params: {
                    ...def.params,
                    [name]: "" as string // 占位值,仅用于类型累积
                }
            }
            // 类型断言让TS识别新的参数集合
            return queryBuilder(innerDef as Query<P | typeof name>["_def"]);
        }
    }
}

// 初始调用时参数集合为空
const c = queryBuilder({ params: {} } as Query["_def"]);
// 每次调用params都会累积参数名到泛型中
const d = c.params("hello").params("world");
d._def.params; // 现在Intellisense会提示hello和world两个属性
// 此处会抛出类型错误,因为{}缺少hello和world必填项
const e: typeof d._def.params = {} 

关键说明

  • 泛型P用来持续追踪所有通过params方法添加的参数名称,每次调用都会把新参数名N合并到集合中。
  • 将params的类型改为映射类型{ [K in P]: string },让TypeScript把P中的每个字符串识别为必填键,从而提供智能提示和类型校验。
  • 构建函数中的类型断言是为了让TypeScript正确推断新的泛型参数,确保类型累积逻辑生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 20:22:53