Skip to content

What’s going on with Object.keys? #6927

@wchargin

Description

@wchargin

The core libdef for Object.keys is clear as can be:

declare class Object {
    // [snip]
    static keys(o: any): Array<string>;
    // [snip]
}

(

static keys(o: any): Array<string>;
)

This suggests that the following code should have a type error:

// @flow
type K = "A" | "B";
const x: {[K]: number} = {};
(Object.keys(x): Array<K>);  // `string` should be incompatible with `K`

And yet the above code typechecks. Why?

This was not always the case. The above code did not typecheck in Flow v0.59.0, but has typechecked since Flow v0.60.0. But the release notes for v0.60.0 don’t mention such a change.

Also, this does not work if the key type is opaque (possibly related to #6569 and friends):

// @flow
declare opaque type O: string;
const y: {[O]: number} = {};
(Object.keys(y): Array<O>);  // fails (sad)

Having the refined type is quite useful, though the grievances in #5210 (from before the change) are legitimate. What is going on? Whence the inconsistency between the libdef, the working example with a transparent subtype of string, and the failing example with an opaque subtype of string?

(Full Flow-Try here.)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions