自定义类型断言守卫导致Builder的data字段为null问题求助
解决Builder类型断言后类型更新异常问题
问题根源
UpdatedBuilderData泛型约束错误:原类型中CurrentData被约束为BuilderData<BuilderSchema>,丢失了当前具体Schema的类型关联,导致TypeScript无法正确计算更新后的Data类型。- 显式固定变量类型:
builder2被显式声明为Builder<typeof schema>,锁定了变量类型,类型断言无法修改显式指定的变量类型,必须让TypeScript自动推断类型才能让断言生效。
修正后的代码
type BuilderSchema = { [k in string]: { data: ReadonlyArray<string> } } type BuilderData<T extends BuilderSchema> = { [k in keyof T]: { value: T[k]["data"][number] } | null } // type helper for blank schema data type NulledOutBuilderData<T extends BuilderSchema> = { [k in keyof T]: null } interface Builder<Schema extends BuilderSchema, Data extends BuilderData<Schema> = NulledOutBuilderData<Schema>> { _data: Data, // chaining setData: < const K extends keyof Schema, const Value extends Exclude<BuilderData<Schema>[K], null>["value"] | null >(key: K, value: Value) => Builder<Schema, UpdatedBuilderData<Schema, Data, K, Value>> // assertions setAndAssertData: < const K extends keyof Schema, const Value extends Exclude<BuilderData<Schema>[K], null>["value"] | null >(key: K, value: Value) => asserts this is Builder<Schema, UpdatedBuilderData<Schema, Data, K, Value>> } // 修正CurrentData的约束为BuilderData<Schema>,关联当前Schema的Data类型 type UpdatedBuilderData< Schema extends BuilderSchema, CurrentData extends BuilderData<Schema>, Key extends keyof Schema, NewValue extends Exclude<BuilderData<Schema>[Key], null>["value"] | null > = { [k in keyof Schema & keyof CurrentData]: k extends Key ? NewValue extends null ? NewValue : { value: NewValue } : CurrentData[k] } const schema = { prop1: { data: [ "hello", "world" ] }, prop2: { data: ["foo", "bar", "baz"] } } as const satisfies BuilderSchema // function that returns a builder of the specified schema declare function createBuilder<const Schema extends BuilderSchema>(schema: Schema): Builder<Schema> // chaining. no problems let builder1 = createBuilder(schema) builder1.setData("prop1", "world").setData("prop2", "baz").setData("prop1", "hello") // 去掉显式类型声明,让TypeScript自动推断 let builder2 = createBuilder(schema) builder2.setAndAssertData("prop1", "world") builder2._data // ^? { prop1: { value: "world" }; prop2: null }
关键修改说明
- 修正
UpdatedBuilderData的泛型约束:将CurrentData extends BuilderData<BuilderSchema>改为CurrentData extends BuilderData<Schema>,确保TypeScript能基于当前具体的Schema计算更新后的Data类型,避免类型丢失。 - 移除显式变量类型声明:
builder2不再显式指定Builder<typeof schema>类型,让TypeScript自动跟踪类型变化,这样setAndAssertData的断言才能正确更新变量的类型。
修改后,builder2._data的类型会正确显示为{ prop1: { value: "world" }; prop2: null },类型断言功能正常,同时保持了类型清晰和智能提示。
内容的提问来源于stack exchange,提问作者A Kam
相关产品推荐
相关产品推荐

