我有一个函数可以将字典转换为具有和属性dictToKv
的对象数组:key
value
/** used to help get type literals versus wide types */
type Narrowable = string | number | boolean | symbol | object | undefined | void | null | {};
/** just like Object.keys() but preserves keyof relationship */
function keys<T extends {}>(obj: T) { Object.keys(obj) as unknown as Array<keyof T> };
/** Helps shape an object into an array where key and value relationship is retained */
type KeyValueFrom<T extends object> = Array<{ [K in keyof T]: { key: K; value: T[K] } }[keyof T]>;
/** convert a dictionary to an array of objects with key and value props */
function dictToKv<N extends Narrowable, T extends Record<string, N>>(obj: T): KeyValueFrom<T> {
return keys(obj).map(k => {
return { key: k, value: obj[k] };
});
}
在我的实用程序的帮助下,我KeyValueFrom<T>
可以显式声明返回的类型,并且这个返回值是不可迭代的,但会保留所有类型的文字信息:
const obj = { id: 123, foo: "bar" } as const;
const kv1 = dictToKv(obj);
for(const kv of kv1) {
if(kv.key === "id") {
// strong types with no unions
type cases = [
Expect<Equal<typeof kv.key, "id">>,
Expect<Equal<typeof kv.value, 123>>
]
}
}
我遇到的问题是相反的。逆向的运行时方面很简单,但困难的部分似乎是创建一个类型实用程序来执行这种逆向转换。
到目前为止,我得到的是:
type DictFrom<T extends { key: string; value: unknown }[]> =
Record<T[number]["key"], T[number]["value"]>;
这确实正确键入了字典的键并维护了文字类型,但值现在是联合类型:
type Inverse = DictFrom<typeof kv1>;
type cases = [
// Expect<Equal<Inverse, typeof obj>>
Expect<Equal<Inverse, { foo: 123 | "bar"; id: 123 | "bar" }>>
];
有没有办法使用 Typescript 的推理来实现非联合类型?