如何为嵌套对象属性实现更精确的TypeScript类型推断?
解决引用表列参数的类型约束问题
问题出在当前的类型参数声明中,RefColName和RefTable的关联没有通过函数参数的类型依赖来驱动TypeScript的类型推断。默认值的使用让TypeScript跳过了基于第一个参数的细化推断,导致第二个参数的类型被放宽为任意字符串。
修正后的实现方案
type Column<T extends string = string, V = unknown> = { internalType: T value: V } type Table = { [column: string]: Column } type Row<T extends Table> = { data: { [C in keyof T]: T[C]['value'] } } type NumberColumn = Column<'int', number> type StringColumn = Column<'str', string> type BooleanColumn = Column<'bool', boolean> type ReferenceColumn<T extends Table = Table> = Column<'ref', Row<T>> & { table: T } type FooTable = { active: BooleanColumn priority: NumberColumn } type BarTable = { name: StringColumn foo: ReferenceColumn<FooTable> } type PickColumns<T extends Table, ColumnType extends Column> = Pick< T, { [C in keyof T]: T[C] extends ColumnType ? C : never }[keyof T] > & { [column: string]: ColumnType } // 重新设计函数类型参数,建立参数间的类型依赖 function columnFromReferenceTable< T extends Table, RefColName extends keyof PickColumns<T, ReferenceColumn> >( referenceColumn: RefColName, // 通过条件类型动态提取被引用表的列名范围 referenceTableColumn: keyof (T[RefColName] extends ReferenceColumn<infer RT> ? RT : never) ) { referenceColumn referenceTableColumn } // 验证场景: columnFromReferenceTable<BarTable>('foo', 'active') // 合法 columnFromReferenceTable<BarTable>('foo', 'priority') // 合法 columnFromReferenceTable<BarTable>('foo', 'wrong') // 报错,符合预期
关键修改点
- 移除冗余默认类型参数:原代码中
RefCols、RefCol等默认参数会干扰TypeScript的类型推断逻辑,现在直接通过条件类型T[RefColName] extends ReferenceColumn<infer RT> ? RT : never,从第一个参数对应的列中动态提取被引用表的结构。 - 建立参数类型关联:第二个参数的类型直接依赖第一个参数的实际传入值,强制TypeScript根据第一个参数选择的引用列,自动约束第二个参数只能是被引用表的有效列名。
这种设计既保留了类型安全性,又简化了函数的类型签名,彻底解决了第二个参数无法被正确约束的问题。
内容的提问来源于stack exchange,提问作者Ryan Palmer
相关产品推荐
相关产品推荐

