Typescript如何利用infer省略泛型参数实现属性类型关联校验
根因分析
你之前给泛型设置默认值失效的原因是:默认值DataType是三个字面量的联合类型,当你不主动指定泛型参数时,TS会直接使用默认的联合类型,此时value的类型也会变为string | number的联合,不再和typ的单个取值绑定,因此失去了关联校验能力。
解决方案
有两种完全不需要暴露泛型参数的实现方式,都可以满足typ和value的类型关联需求:
方案1:生成联合类型(推荐,直接用于类型标注)
直接通过映射类型把原来的泛型接口转换为固定的联合类型,不需要定义泛型参数:
type DataType = "string"|"number"|"date"; type DataTypeMapping = { "string": string; "number": number; "date": string; } // 直接生成联合类型,无泛型参数 type LinkedTypesSample = { [T in DataType]: { typ: T; value: DataTypeMapping[T] } }[DataType]
使用时直接标注类型即可,自动关联校验:
// 校验通过 const stringInstance: LinkedTypesSample = { typ: "string", value: "abc" } // 校验通过 const numberInstance: LinkedTypesSample = { typ: "number", value: 1 } // 校验报错:typ为number时value不能是字符串 const errorInstance: LinkedTypesSample = { typ: "number", value: "123" }
方案2:工厂函数推导(适合创建时自动推导类型,无需手动标注)
如果不想手动写类型标注,可以通过工厂函数利用TS的泛型自动推导能力:
type DataType = "string"|"number"|"date"; type DataTypeMapping = { "string": string; "number": number; "date": string; } interface LinkedTypesSample <T extends DataType> { typ: T; value: DataTypeMapping[T]; } // 辅助创建函数,自动推导泛型 function createSample<T extends DataType>(sample: LinkedTypesSample<T>) { return sample; }
使用时直接传参即可,不需要指定泛型也不需要手动标注变量类型:
// 自动推导为LinkedTypesSample<"string">类型 const stringInstance = createSample({ typ: "string", value: "abc" }); // 自动推导为LinkedTypesSample<"number">类型 const numberInstance = createSample({ typ: "number", value: 1 }); // 报错:类型不匹配 const errorInstance = createSample({ typ: "number", value: "123" });
内容的提问来源于stack exchange,提问作者Nyavro
相关产品推荐
相关产品推荐

