如何在TypeScript泛型中强制字段类型与另一字段一致?
类型一致性约束的高效实现方案
场景1:强制master与slave值类型严格匹配
给定以下代码,需要实现MyType,确保slave的类型与master完全一致:
type MyStr = "one" | "two" | "three"; const x: MyType<MyStr> = { master: "one", slave: "one" }; // 应编译通过 const y: MyType<MyStr> = { master: "one", slave: "two" }; // 应编译失败
原方案的问题
原方案通过映射类型生成所有可能的键值组合,再通过索引获取最终类型:
type MyType<T extends string> = { [K in T]: { master: K, slave: K } }[T];
该方案虽能满足需求,但当T包含大量成员时,会生成庞大的中间映射类型,导致TypeScript服务过载崩溃。
优化方案
利用TypeScript联合类型的条件类型分发特性,无需预生成所有映射组合,直接推导每个成员对应的约束类型:
type MyType<T extends string> = T extends infer K ? { master: K; slave: K } : never;
当T为联合类型时,条件类型会自动对每个成员进行处理,最终返回所有符合约束的类型联合,性能远优于原方案。
场景2:ElementFieldType的类型一致性约束
实际需求中,需要确保name指定的键与Element组件的value/onChange参数类型严格匹配:
type ElementFieldType<T, K extends keyof T> = { name: K; Element: FC<{ value: T[K], onChange: (value: T[K]) => void }>; }
优化方案
同样利用条件类型分发特性,避免生成中间映射对象,提升性能:
import { FC } from 'react'; type ElementFieldType<T> = keyof T extends infer K ? K extends keyof T ? { name: K; Element: FC<{ value: T[K], onChange: (value: T[K]) => void }>; } : never : never;
使用时无需显式指定K,TypeScript会自动推导name对应的类型,并约束Element的props类型:
type FormData = { username: string; age: number }; // 编译通过:name与Element类型匹配 const validField: ElementFieldType<FormData> = { name: 'username', Element: ({ value, onChange }) => <input value={value} onChange={(e) => onChange(e.target.value)} /> }; // 编译失败:name为age,但Element处理的是string类型 const invalidField: ElementFieldType<FormData> = { name: 'age', Element: ({ value, onChange }) => <input value={value} onChange={(e) => onChange(e.target.value)} /> };
内容的提问来源于stack exchange,提问作者erano
相关产品推荐
相关产品推荐

