Другие ответы великолепны, но я не вижу ничего, что касалось системы типов, специфичной для TypeScript. Следующие определения типов и сигнатура должны позволить компилятору понять тип транспонированного объекта (при условии TS2.8 +):
type AllKeys<T> = T extends any ? keyof T : never;
type RelevantKeys<T, K extends keyof T[keyof T]> = {
[L in keyof T]: K extends keyof T[L] ? L : never
}[keyof T];
type Transpose<T> = {
[K in AllKeys<T[keyof T]>]: {
[L in RelevantKeys<T, K>]: T[L][K]
}
};
function transpose<T extends object & Record<keyof T, object>>(t: T): Transpose<T>;
// one possible implementation, use your favorite from above
function transpose(t: { [k: string]: { [l: string]: any } }) {
const ret = {} as { [l: string]: { [k: string]: any } };
Object.keys(t).forEach(k =>
Object.keys(t[k]).forEach(l => {
if (!(l in ret)) ret[l] = {};
ret[l][k] = t[k][l];
})
);
return ret;
}
Соблюдайте типы:
var obj = {
Key_1: { Head_1: "val_11", Head_2: "val_21", Head_3: "val_31" },
Key_2: { Head_1: "val_12", Head_2: "val_22", Head_3: "val_32" },
Key_3: { Head_1: "val_13", Head_2: "val_23", Head_3: "val_33" }
}
const transposed = transpose(obj);
// the following are compile-time IntelliSense and/or error messages
transposed.Head_1; // {Key_1: string, Key_2: string, Key_3: string};
transposed.Haed_2; // error, property Haed2 does not exist
transposed.Head_3.Key_2; // string
const x = { a: { b: 1, c: true }, d: { e: "hey", f: undefined } };
const y = transpose(x);
y.e.d; // string
y.e.a; // error, property 'a' does not exist on {d: string}
y.b.a; // number
y.b.d; // error, property 'd' does not exist on {a: number}
Надеюсь, это поможет!