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

如何利用Schema数组推断TypeScript对象类型

如何利用Schema数组推断TypeScript对象类型

嘿,我完全懂你的需求——不想手动重复写对象类型,而是希望通过已有的Schema数组自动推断出对应的TypeScript类型对吧?这确实能减少冗余代码,还能保证类型和Schema的一致性,咱们一步步来搞定它:

首先明确核心思路:把Schema里每个Field的name作为对象属性名,kind映射成TS原生类型,再根据required标记判断属性是必填还是可选。

第一步:定义Kind到TS类型的映射工具

先写一个工具类型,把Schema里的kind字符串转换成TypeScript的原生类型:

type KindToType<K extends Field['kind']> = 
  K extends 'string' ? string :
  K extends 'integer' | 'float' ? number :
  K extends 'bool' ? boolean :
  never;

这个类型会根据传入的kind值返回对应TS类型——比如'integer'和'float'都对应number,'string'对应string,以此类推。

第二步:从Schema推断对象类型的核心工具

接下来写核心工具类型,接收Schema类型后生成对应的对象类型:

type InferFromSchema<S extends Schema> = 
  // 处理必填字段:仅保留required为true的字段
  { [F in S['fields'][number] as F['name']]: F extends { required: true } ? KindToType<F['kind']> : never } &
  // 处理可选字段:保留required为false或未定义的字段,标记为可选
  { [F in S['fields'][number] as F['name']]?: F extends { required: true } ? never : KindToType<F['kind']> } extends infer O
    // 移除类型为never的无效属性,避免冗余
    ? { [K in keyof O as O[K] extends never ? never : K]: O[K] }
    : never;

第三步:实际使用推断类型

现在就可以用这个工具类型来推断customer的类型了:

type Field = {
    name: string
    kind: 'string' | 'integer' | 'float' | 'bool'
    required?: boolean
}
type Schema = { fields: Field[] };

const schema: Schema = {
    fields: [
        { name: 'id', kind: 'integer', required: true },
        { name: 'name', kind: 'string', required: true },
        { name: 'debits', kind: 'float' },
    ]
}

// 自动推断出类型:{ id: number; name: string; debits?: number }
type Customer = InferFromSchema<typeof schema>;

// customer会严格遵循推断出的类型
const customer: Customer = {
  id: 1,
  name: 'John Doe',
  debits: 50 // 这个字段可选,写不写都符合类型要求
}

额外优化:用const断言提升类型精度

如果你的Schema是固定不变的常量,还可以用as const断言让TypeScript推断出更精确的字面量类型,不用依赖Field和Schema类型注解也能正常工作:

const schema = {
    fields: [
        { name: 'id', kind: 'integer', required: true },
        { name: 'name', kind: 'string', required: true },
        { name: 'debits', kind: 'float' },
    ] as const
} as const;

// 调整工具类型适配常量场景
type InferFromConstSchema<S extends { fields: readonly any[] }> = 
  { [F in S['fields'][number] as F['name']]: F extends { kind: infer K } ? 
    K extends 'string' ? string :
    K extends 'integer' | 'float' ? number :
    K extends 'bool' ? boolean : never : never } &
  { [F in S['fields'][number] as F['name']]?: F extends { required: true } ? never : 
    F extends { kind: infer K } ? 
    K extends 'string' ? string :
    K extends 'integer' | 'float' ? number :
    K extends 'bool' ? boolean : never : never } extends infer O
    ? { [K in keyof O as O[K] extends never ? never : K]: O[K] }
    : never;

type Customer = InferFromConstSchema<typeof schema>;

这种方式下,TypeScript会精确识别每个字段的字面量值,推断出的类型会更严谨。

备注:内容来源于stack exchange,提问作者Belizário Ribeiro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.16 09:52:59