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

如何为嵌套对象属性实现更精确的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 11:24:54