tsafe icon indicating copy to clipboard operation
tsafe copied to clipboard

Enable to typesafely compose Object.fromEntries and Object.entries

Open garronej opened this issue 2 years ago • 2 comments

It would be really powerful to be able to apply transformation to an object using the well-known pattern:

const transformedObject= Object.fromEntries(
    Object.entries(originalObject)
        .map(([key, value])=> [key, f(value)]
);

And have TypeScript infers the type of transformedObject based on the transformation applied to the values f(value).

We are half way there already with the utilities:

But the typing of fromEntires() would have to be improved a bit so that the following example would pass:

import { Reflect } from "tsafe/Reflect";
import { assert } from "tsafe/assert";
import type { Equals } from "tsafe";
import { objectEntries } from "tsafe/objectEntries";
import { fromEntires } from "tsafe/objectFromEntries";

const originalObject = Reflect<{
    a: string;
    b: string;
}>();

const modifiedObject = objectFromEntries(
    objectEntries(originalObject)
        .map(([key, value]) => [key, value.length] as const)
);

type ExpectedTypeOfModifiedObject = {
    a: number;
    b: number;
};

assert<Equals<typeof modifiedObject, ExpectedTypeOfModifiedObject>>();

In the current version of tsafe we're getting this:
image

garronej avatar Oct 09 '22 22:10 garronej

The test that would have to pass in src/test/objectFromEntires.types.ts:

{

    const originalObject = Reflect<Record<"a" | "b",string>>();

    const entries = objectEntries(originalObject);

    assert<Equals<typeof entries, (["a", string] | ["b", string])[]>>();

    const transformedEntries = entries.map(([key, value]) => [key, value.length] as const);

    assert<Equals<typeof transformedEntries, (readonly ["a" | "b", number])[]>>();

    const modifiedObject = objectFromEntries(transformedEntries);

    assert<Equals<typeof modifiedObject, Record<"a" | "b", number>>>();

}

garronej avatar Oct 09 '22 22:10 garronej

That looks nice and it should be perfectly possible! I am currently working on an internal project that does something related. I will keep you updated!

danieldietrich avatar Oct 13 '22 07:10 danieldietrich