如何在TypeScript中结合泛型使用元组实现类型安全映射
实现类型安全的泛型映射对象(仅定义一次键值对)
我想要实现一个类型安全的映射对象,只需要定义一次键值对。目前已经完成了以下代码:
const myPropTuple = [ [0, "cat"], [1, "dog"], [2, "bird"] ] as const; type TMyPropKey = TInnerTupple<typeof myPropTuple>[0]; type TMyPropValue = TInnerTupple<typeof myPropTuple>[1]; function getMyProp(val: number) { type TKey = TInnerTupple<typeof myPropTuple>[0]; const mapA2 = new Map(myPropTuple); if(!mapA2.has(val as TKey)) throw new RangeError("unexpected value"); return mapA2.get(val as TKey); } // 工具类型(无需内联) type TTupleType<T extends Iterable<any>> = T extends ReadonlyArray<infer R> ? R :never; type TInnerTupple<I extends Iterable<any>> = TTupleType<I>; // 测试用例 console.assert(getMyProp(1) === "dog"); //console.assert(getMyProp(1) === "turle"); // 触发编译错误 const a: TMyPropValue = "cat"; //const b: TMyPropValue = "eagle"; // 触发编译错误
但我希望将这个函数改造成泛型形式,同时保留类型安全,最终能写出这样的代码:
const myPropTuple = [ [0, "cat"], [1, "dog"], [2, "bird"] ] as const; console.assert(getGenericProp(myPropTuple, 1) === "dog"); const yourPropTuple = [ [0, "fish"], [1, "towel"], [2, "whale"] ] as const; console.assert(getGenericProp(yourPropTuple, 0) === "fish");
并且以下代码需要触发编译错误:
console.assert(getGenericProp(myPropTuple, 1) === "turle"); // 触发编译错误 type TYourPropValue = TInnerTupple<typeof yourPropTuple>[1]; const y: TYourPropValue = "dog"; // 触发编译错误
补充说明
@jcalz提出了一个更简洁的替代方案,扩展后如下:
const animalProps = { 0: "cat", 1: "dog", 2: "bird" } as const; function getGenericProp2<T extends object>(props: T, val: keyof T): T[keyof T] { const found = props[val]; if(found === undefined) throw new RangeError("unexpected value"); return found; } type TValues = ValueOf<typeof animalProps>; type TKeys = keyof typeof animalProps;
内容的提问来源于stack exchange,提问作者bnieland
相关产品推荐
相关产品推荐

