如何在TypeScript中基于字面量值创建条件映射类型?
问题解决:基于StreamDefinition生成条件映射类型
原始代码定义
interface StreamDefinition<D> { parser: (data: Record<string, string>) => D | null; streamType: string; defaultStreamName: string; patternStream: boolean; } const aStreamDefinition: StreamDefinition<number> = { parser: (data) => parseInt(data['val']), streamType: 'streamA', defaultStreamName: 'data:A', patternStream: false, }; const bStreamDefinition: StreamDefinition<string> = { parser: (data) => data['val'], streamType: 'StreamB', defaultStreamName: 'data:B:*:stream', patternStream: true, }; export const streams = { A: aStreamDefinition, B: bStreamDefinition, }; type StreamsDefinitions = typeof streams;
需求
生成映射类型FinalDataType,包含streams的所有键,值规则:
- 若对应
StreamDefinition的patternStream为true,值为{[key: string]: D}(D为parser返回的非null类型) - 若
patternStream为false,值为D本身
现有代码问题
你的条件类型全部返回字典类型,原因是StreamsDefinitions[T]['patternStream']被推断为宽泛的boolean类型,而非具体的true/false字面量,导致条件判断永远走else分支。
解决方案
步骤1:保留patternStream的字面量类型
给streams添加as const断言,让TypeScript保留每个patternStream的具体字面量值:
export const streams = { A: aStreamDefinition, B: bStreamDefinition, } as const;
步骤2:修正条件映射类型
由于parser返回D | null,用Exclude剔除null类型,得到纯净的D类型:
type FinalDataType = { [T in keyof StreamsDefinitions]: StreamsDefinitions[T]['patternStream'] extends true ? { [key: string]: Exclude<ReturnType<StreamsDefinitions[T]['parser']>, null> } : Exclude<ReturnType<StreamsDefinitions[T]['parser']>, null>; };
验证
此时FinalDataType的类型为:
type FinalDataType = { A: number; B: { [key: string]: string; }; }
完全符合示例对象的类型要求。
内容的提问来源于stack exchange,提问作者Algirdyz
相关产品推荐
相关产品推荐

