Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ES2019 Object.fromEntries function #30934

Merged
merged 5 commits into from
Apr 30, 2019

Conversation

saschanaz
Copy link
Contributor

@saschanaz saschanaz commented Apr 15, 2019

Fixes #30933, fixes #25999

We already have #26149 but it hasn't been active nor reached a good consensus, so this PR adds a simpler type with potential future progressive enhancement with generics.

* Returns an object created by key-value entries for properties and methods
* @param entries An iterable object that contains key-value entries for properties and methods.
*/
fromEntries(entries: Iterable<[string | symbol, any]>): any;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be really ideal if this could produce an object where the values matched the value item in the iterable. Perhaps?:

Suggested change
fromEntries(entries: Iterable<[string | symbol, any]>): any;
fromEntries<T = unknown>(entries: Iterable<[PropertyKey, T]>): { [k in PropertyKey]: T };

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion, but a bit hesitant to do unknown here as no other function in lib.d.ts uses it for its return type. Would any be sufficient or unknown be required?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since T is inferable then any is fine, but imo nothing should ever be any, only unknown or narrower :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kinda agree but I'll go any for now, for consistency here...

* Returns an object created by key-value entries for properties and methods
* @param entries An iterable object that contains key-value entries for properties and methods.
*/
fromEntries<T = any>(entries: Iterable<[PropertyKey, T]>): { [k in PropertyKey]: T };

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fromEntries<T = any>(entries: Iterable<[PropertyKey, T]>): { [k in PropertyKey]: T };
fromEntries<T = any>(entries: Iterable<readonly [PropertyKey, T]>): { [k in PropertyKey]: T };

See #29721

@RyanCavanaugh
Copy link
Member

@daniel19801 DANIEL PLEASE READ! - You cannot turn off GitHub email notifications by replying with "stop" or some variant thereof; all this is doing is posting comments to GitHub threads. Please go to your GitHub profile and turn off email notifications.

@ljharb
Copy link
Contributor

ljharb commented Apr 26, 2019

@saschanaz it'd also be great if you wanted to create a DT package for https://www.npmjs.com/package/object.fromentries using these types, once this PR is merged :-)

@microsoft microsoft deleted a comment Apr 30, 2019
@RyanCavanaugh RyanCavanaugh merged commit 49d6f61 into microsoft:master Apr 30, 2019
@AWare
Copy link

AWare commented May 14, 2019

Apologies if this is the wrong place for this but I was playing with this type locally with the package. (Which has really helped me out, so massive thanks 🎉
@saschanaz)

If I have something of the form {[x: string]: A} and take it to an array and back I get {[x: string]:A; [x: number]: A}

This goes away if I make a second type parameter for fromEntries which extends PropertyKey
<K extends PropertyKey, T = any>(entries: Iterable<readonly [K, T]>): { [k in K]: T };

@saschanaz saschanaz deleted the es2019-object branch May 14, 2019 10:00
@saschanaz
Copy link
Contributor Author

saschanaz commented May 14, 2019

@AWare That suggestion looks good, you can open a new issue so that the project maintainers can start thinking about it.

@AnyhowStep
Copy link
Contributor

AnyhowStep commented Jul 3, 2019

If anyone is looking for something with more generic hacking,

Playground

type PairToObject<P extends readonly [PropertyKey, any]> = (
    P extends any ?
    {
        [k in P[0]] : P[1]
    } :
    never
);
type ToUnaryFunctionUnion<U> = (
    U extends any ?
    (arg : U) => void :
    never
);
type UnionToIntersection<U> = (
    ToUnaryFunctionUnion<U> extends (arg : infer I) => void ?
    I :
    never
);
type _<T> = T;
type Merge<T> = _<{ [k in keyof T] : T[k] }>;

declare function fromEntries<
    P extends readonly [PropertyKey, any]
> (i : Iterable<P>) : (
    /**
     * The `Merge<>` part isn't necessary.
     */
    Merge<
        UnionToIntersection<
            PairToObject<P>
        >
    >
);

declare const entries : [
    ["a", 1],
    ["b", 2]
];
/*
    OK!
    {
        a: 1;
        b: 2;
    }
*/
const x = fromEntries(entries);
/*
    OK!
    {
        a: 1;
        b: 2;
    }
*/
const y = fromEntries([
    ["a", 1],
    ["b", 2]
] as const);
/*
    NOT WHAT WE EXPECTED,

    {
        [x: string]: number;
    }

    So, the `as const` "hack" is needed
*/
const z = fromEntries([
    ["a", 1],
    ["b", 2]
]);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add ES2019 Object.fromEntries function proposal-object-from-entries
6 participants