Skip to content

Commit

Permalink
[fei4636.2] Add keys() method (#315)
Browse files Browse the repository at this point in the history
## Summary:
This adds an wrapper around `Object.keys` that returns `Array<$Keys<O>>` instead of `Array<string>`.

Issue: FEI-4636

## Test plan:
`yarn test`
`yarn flow`

Author: somewhatabstract

Reviewers: jeresig, kevinbarabash, benchristel, maddy531

Required Reviewers:

Approved By: jeresig, kevinbarabash, benchristel

Checks: ⌛ Prime node_modules cache for primary configuration (ubuntu-latest, 16.x), ⌛ gerald, ⌛ Analyze (javascript), ⏭  dependabot

Pull Request URL: #315
  • Loading branch information
somewhatabstract authored Jul 11, 2022
1 parent e7e3b5f commit 0a7b461
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/jeff-wrote-this.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@khanacademy/wonder-stuff-core": minor
---

Add `keys` method as strongly-typed alternative to `Object.keys`
34 changes: 34 additions & 0 deletions packages/wonder-stuff-core/src/__tests__/keys.flowtest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// @flow
import {keys} from "../keys.js";

{
// should type returned array element as subtype of string
const obj1 = {
a: 1,
b: "2",
};

const keys1 = keys(obj1);
const _: string = keys1[0];
}

{
// should type returned array element as supertype of keys
const obj2 = {
a: 1,
b: "2",
c: [3, 4],
};

// This works because the return type is an array of a supertype of all key
// names, thanks to $Keys<>.
const keys2ok = keys(obj2);
const _: "a" | "b" | "c" = keys2ok[0];

// This errors because we try to get a key of only one type. Flow sees this
// as a bad call rather than a bad assignment. Hence the expectation on
// the callsite, not the assignment.
// $FlowExpectedError[incompatible-call]
const keys2bad = keys(obj2);
const __: "a" = keys2bad[0];
}
36 changes: 36 additions & 0 deletions packages/wonder-stuff-core/src/__tests__/keys.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// @flow
import {keys} from "../keys.js";

describe("#keys", () => {
it("should call Object.keys with the given object", () => {
// Arrange
const keysSpy = jest.spyOn(Object, "keys");
const obj = {
a: 1,
b: "2",
c: [3, 4],
};

// Act
keys(obj);

// Assert
expect(keysSpy).toHaveBeenCalledWith(obj);
});

it("should return the result of Object.keys", () => {
// Arrange
const obj = {
a: 1,
b: "2",
c: [3, 4],
};
jest.spyOn(Object, "keys").mockReturnValueOnce("THE RESULT");

// Act
const result = keys(obj);

// Assert
expect(result).toEqual("THE RESULT");
});
});
1 change: 1 addition & 0 deletions packages/wonder-stuff-core/src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// @flow
export {clone} from "./clone.js";
export {keys} from "./keys.js";
export {values} from "./values.js";
export {Errors} from "./errors.js";
export {errorsFromError, Order} from "./errors-from-error.js";
Expand Down
11 changes: 11 additions & 0 deletions packages/wonder-stuff-core/src/keys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// @flow
/**
* Return an array of the enumerable keys of an object.
*
* @param {$ReadOnly<{[string]: mixed}>} obj The object for which the values are
* to be returned.
* @returns {Array<$Keys<O>>} An array of the enumerable keys of an object.
*/
export function keys<O: {[string]: mixed}>(obj: O): Array<$Keys<O>> {
return Object.keys(obj);
}

0 comments on commit 0a7b461

Please sign in to comment.