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

TypeScript条件类型困惑:多键schemas下NumericColumnKeys解析为never

问题:TypeScript提取数值类型字段键时返回never的问题

代码示例

以下代码中:

const schemas = {
  foo: {
    date1: {
      display: 'date',
      type: 'date',
    },
    text1: {
      display: 'text',
      type: 'text',
    },
    number1: {
      display: 'number',
      type: 'number',
    },
  },
  bar: {
    date2: {
      display: 'date',
      type: 'date'
    },
    text2: {
      display: 'text',
      type: 'text'
    },
    number2: {
      display: 'number',
      type: 'number'
    }
  },
} as const
    
function schema(schemaType: keyof typeof schemas) {
  const fields = schemas[schemaType]
  
  type NumericColumnKeys = {
    [K in keyof typeof fields]: (typeof fields)[K] extends {
      type: 'number'
    }
      ? K
      : never
  }[keyof typeof fields]
}

问题现象

NumericColumnKeys会被解析为never,但当schemas仅包含单个键(比如只有foo)时,代码能正常工作:

const schemas = {
  foo: {
    date1: {
      display: 'date',
      type: 'date',
    },
    text1: {
      display: 'text',
      type: 'text',
    },
    number1: {
      display: 'number',
      type: 'number',
    },
  }
} as const
// ... 其余代码同上

需求背景

我需要从配置对象动态生成验证schema,核心目标是根据子对象的type值提取对应键名,以此构建Typebox验证器。

解决方案

问题根源在于函数内部的类型推导:当schemas包含多个键时,typeof fields会被推断为所有子类型的联合类型,导致映射类型无法正确过滤出type: 'number'的键。

可以通过将类型逻辑提取到泛型参数中解决,让TypeScript在调用时就确定具体的子类型:

const schemas = {
  foo: {
    date1: {
      display: 'date',
      type: 'date',
    },
    text1: {
      display: 'text',
      type: 'text',
    },
    number1: {
      display: 'number',
      type: 'number',
    },
  },
  bar: {
    date2: {
      display: 'date',
      type: 'date'
    },
    text2: {
      display: 'text',
      type: 'text'
    },
    number2: {
      display: 'number',
      type: 'number'
    }
  },
} as const

// 通用工具类型:提取指定type对应的键
type ExtractKeysByType<T, Type> = {
  [K in keyof T]: T[K] extends { type: Type } ? K : never
}[keyof T]

// 泛型函数:调用时锁定具体子类型
function schema<T extends keyof typeof schemas>(schemaType: T) {
  const fields = schemas[schemaType]
  
  // 现在能正确提取数值类型的键
  type NumericColumnKeys = ExtractKeysByType<typeof fields, 'number'>
  // 此处可基于NumericColumnKeys构建Typebox验证器
}

// 验证:调用时类型推导正常
schema('foo') // NumericColumnKeys 为 'number1'
schema('bar') // NumericColumnKeys 为 'number2'

这种方式通过泛型参数在函数调用阶段锁定具体的子类型,让映射类型可以准确过滤目标键。如果需要提取其他类型(如text、date),直接复用ExtractKeysByType工具类型即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 21:53:27