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
相关产品推荐
相关产品推荐

