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

TypeScript中表单配置构建器的类对象类型动态推断问题

表单配置构建器的TypeScript类型推断问题

问题背景

我正在构建一个表单配置构建器,希望能动态推断类型,以下是最小复现代码:

interface Meta {
    optional: boolean
}

class Base<Type = any> {
    readonly _type!: Type
    baseMeta: Meta

    constructor() {
        this.baseMeta = {
            optional: false,
        }
    }

    optional() {
        this.baseMeta.optional = true
        return this;
    }
}

class FieldText extends Base<string> {

}

class FieldNumber extends Base<number> {

}


class Field {
    static text() {
        return new FieldText();
    }

    static number() {
        return new FieldNumber();
    }
}

const fields = {
    fieldText: Field.text(),
    fieldNumber: Field.number(),
    fieldTextOptional: Field.text().optional(),
    fieldNumberOptional: Field.number().optional(),
}

期望的类型结果

希望实现以下两种类型之一:

type ExpectedType = {
    fieldText: string;
    fieldNumber: number;
    fieldTextOptional: string | undefined;
    fieldNumberOptional: number | undefined;
}

或者:

type ExpectedTypeWithOptionalKeys = {
    fieldText: string;
    fieldNumber: number;
    fieldTextOptional?: string;
    fieldNumberOptional?: number;
}

尝试的方案及问题

我尝试进行类型推断,但optional属性未被纳入考量:

type ExtractFieldType<O, T> = O extends true ? T | undefined : T;

type SchemaType<T extends Record<string, Base>> = {
    [Property in keyof T]: ExtractFieldType<T[Property]['baseMeta']['optional'], T[Property]['_type']>;
};

type Schema = SchemaType<typeof fields>;

当前Schema的结果为:

type Schema = {
    fieldText: string;
    fieldNumber: number;
    fieldTextOptional: string;
    fieldNumberOptional: number;
}

其中O extends true ? T | undefined : T始终返回T,未考虑optional的实际值。

最终实现方案

参考@kelly的回答调整optional函数后,最终实现如下:

optional<T extends boolean>(value?: T): Base<Type, T> {
    const optional = typeof value === 'boolean' ? value : true;
    this.baseMeta.optional = optional as boolean;
    return this as unknown as Base<Type, T>;
}

最初无法设置默认值,否则TypeScript会报错:

Type 'boolean' is not assignable to type 'T'.
  'boolean' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'boolean'.(2322)

因此将value设为可选参数,其余部分按说明实现,若移除as unknown会出现以下错误:

Conversion of type 'this' to type 'Base<Type, T>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Type 'Base<Type, boolean>' is not comparable to type 'Base<Type, T>'.
    Type 'boolean' is not comparable to type 'T'.
      'boolean' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'boolean'.(2352)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:35:32