From 6d923da266cc2a61e3c585ed1a8e08b54baa65c7 Mon Sep 17 00:00:00 2001 From: Jaco Date: Mon, 8 Nov 2021 09:09:26 +0100 Subject: [PATCH] object{Entries, Keys, Values} (#1169) * object{Entries, Keys, Values} * Use objectKeys as applicable * tighten schema defs * Linting issue snuck in --- CHANGELOG.md | 1 + packages/networks/src/crosscheck.spec.ts | 6 +++--- packages/networks/src/types.ts | 2 +- packages/util/src/object/clear.ts | 4 ++++ packages/util/src/object/copy.ts | 4 ++++ packages/util/src/object/entries.spec.ts | 18 ++++++++++++++++++ packages/util/src/object/entries.ts | 14 ++++++++++++++ packages/util/src/object/index.ts | 3 +++ packages/util/src/object/keys.spec.ts | 17 +++++++++++++++++ packages/util/src/object/keys.ts | 10 ++++++++++ packages/util/src/object/property.ts | 8 ++++++++ packages/util/src/object/spread.ts | 10 ++++++++-- packages/util/src/object/values.spec.ts | 17 +++++++++++++++++ packages/util/src/object/values.ts | 12 ++++++++++++ 14 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 packages/util/src/object/entries.spec.ts create mode 100644 packages/util/src/object/entries.ts create mode 100644 packages/util/src/object/keys.spec.ts create mode 100644 packages/util/src/object/keys.ts create mode 100644 packages/util/src/object/values.spec.ts create mode 100644 packages/util/src/object/values.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index c7f79da53..a3e7a548e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Changes: - Add `stringPascalCase` utility +- Add strongly typed `object{Entries, Keys, Values}` utilities ## 7.8.2 Nov 7, 2021 diff --git a/packages/networks/src/crosscheck.spec.ts b/packages/networks/src/crosscheck.spec.ts index a872c910c..123be564d 100644 --- a/packages/networks/src/crosscheck.spec.ts +++ b/packages/networks/src/crosscheck.spec.ts @@ -1,11 +1,11 @@ // Copyright 2017-2021 @polkadot/networks authors & contributors // SPDX-License-Identifier: Apache-2.0 -import type { KnownSubstrate, Ss58Registry } from './types'; +import type { Ss58Registry } from './types'; import fs from 'fs'; -import { stringify } from '@polkadot/util'; +import { objectKeys, stringify } from '@polkadot/util'; import { fetch } from '@polkadot/x-fetch'; import { substrateRegistry } from './defaults'; @@ -52,7 +52,7 @@ describe('check latest Substrate ss58 registry', (): void => { }); it('has the same values as the original', (): void => { - const fields = Object.keys(original.schema) as (keyof KnownSubstrate)[]; + const fields = objectKeys(original.schema); const errors = original.registry .map((n): [string, string[]] => { const other = allNetworks.find(({ prefix }) => prefix === n.prefix); diff --git a/packages/networks/src/types.ts b/packages/networks/src/types.ts index 17f6d8471..3e8b8d707 100644 --- a/packages/networks/src/types.ts +++ b/packages/networks/src/types.ts @@ -37,5 +37,5 @@ export interface Network extends SubstrateNetwork { export interface Ss58Registry { registry: KnownSubstrate[]; specification: string; - schema: Record; + schema: Record; } diff --git a/packages/util/src/object/clear.ts b/packages/util/src/object/clear.ts index 5d049a839..dfefadcb4 100644 --- a/packages/util/src/object/clear.ts +++ b/packages/util/src/object/clear.ts @@ -1,6 +1,10 @@ // Copyright 2017-2021 @polkadot/util authors & contributors // SPDX-License-Identifier: Apache-2.0 +/** + * @name objectClear + * @summary Removes all the keys from the input object + */ export function objectClear (value: Record): Record { const keys = Object.keys(value); diff --git a/packages/util/src/object/copy.ts b/packages/util/src/object/copy.ts index eb98e6bfd..cef182495 100644 --- a/packages/util/src/object/copy.ts +++ b/packages/util/src/object/copy.ts @@ -3,6 +3,10 @@ import { objectSpread } from './spread'; +/** + * @name objectCopy + * @summary Creates a shallow clone of the input object + */ export function objectCopy (source: T): T { return objectSpread({}, source); } diff --git a/packages/util/src/object/entries.spec.ts b/packages/util/src/object/entries.spec.ts new file mode 100644 index 000000000..c049fe056 --- /dev/null +++ b/packages/util/src/object/entries.spec.ts @@ -0,0 +1,18 @@ +// Copyright 2017-2021 @polkadot/util authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import { objectEntries } from '.'; + +describe('objectEntries', (): void => { + it('extracts all entries', (): void => { + const o = { a: 1, b: 2, c: 3 }; + const entries = objectEntries(o); + + expect(entries).toEqual([['a', 1], ['b', 2], ['c', 3]]); + + for (const [k, v] of entries) { + expect(k).toBeDefined(); + expect(v).toBeDefined(); + } + }); +}); diff --git a/packages/util/src/object/entries.ts b/packages/util/src/object/entries.ts new file mode 100644 index 000000000..ca95f8798 --- /dev/null +++ b/packages/util/src/object/entries.ts @@ -0,0 +1,14 @@ +// Copyright 2017-2021 @polkadot/util authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +type Entries = { + [K in keyof T]: [K, T[K]] +}[keyof T][]; + +/** + * @name objectEntries + * @summary A version of Object.entries that is typed for TS + */ +export function objectEntries (obj: T): Entries { + return Object.entries(obj) as Entries; +} diff --git a/packages/util/src/object/index.ts b/packages/util/src/object/index.ts index a71ae216d..f3c64b208 100644 --- a/packages/util/src/object/index.ts +++ b/packages/util/src/object/index.ts @@ -3,5 +3,8 @@ export { objectClear } from './clear'; export { objectCopy } from './copy'; +export { objectEntries } from './entries'; +export { objectKeys } from './keys'; export { objectProperty, objectProperties } from './property'; export { objectSpread } from './spread'; +export { objectValues } from './values'; diff --git a/packages/util/src/object/keys.spec.ts b/packages/util/src/object/keys.spec.ts new file mode 100644 index 000000000..72da43982 --- /dev/null +++ b/packages/util/src/object/keys.spec.ts @@ -0,0 +1,17 @@ +// Copyright 2017-2021 @polkadot/util authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import { objectKeys } from '.'; + +describe('objectKeys', (): void => { + it('extracts all keys', (): void => { + const o = { a: 1, b: 2, c: 3 }; + const keys = objectKeys(o); + + expect(keys).toEqual(['a', 'b', 'c']); + + for (const k of keys) { + expect(o[k]).toBeDefined(); + } + }); +}); diff --git a/packages/util/src/object/keys.ts b/packages/util/src/object/keys.ts new file mode 100644 index 000000000..2766595f0 --- /dev/null +++ b/packages/util/src/object/keys.ts @@ -0,0 +1,10 @@ +// Copyright 2017-2021 @polkadot/util authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +/** + * @name objectKeys + * @summary A version of Object.keys that is typed for TS + */ +export function objectKeys> (value: T): K[] { + return Object.keys(value) as K[]; +} diff --git a/packages/util/src/object/property.ts b/packages/util/src/object/property.ts index 1d046a7ba..ec089d369 100644 --- a/packages/util/src/object/property.ts +++ b/packages/util/src/object/property.ts @@ -3,6 +3,10 @@ import { isUndefined } from '../is/undefined'; +/** + * @name objectProperty + * @summary Assign a get property on the input object + */ export function objectProperty (that: object, key: string, getter: (k: string) => unknown): void { // We use both the hasOwnProperty as well as isUndefined checks here, since it may be set // in inherited classes and _Own_ properties refers to the class only, not only parents @@ -13,6 +17,10 @@ export function objectProperty (that: object, key: string, getter: (k: string) = } } +/** + * @name objectProperties + * @summary Assign get properties on the input object + */ export function objectProperties (that: object, keys: string[], getter: (k: string, i: number) => unknown): void { for (let i = 0; i < keys.length; i++) { objectProperty(that, keys[i], (k) => getter(k, i)); diff --git a/packages/util/src/object/spread.ts b/packages/util/src/object/spread.ts index db79b43fa..663e91f50 100644 --- a/packages/util/src/object/spread.ts +++ b/packages/util/src/object/spread.ts @@ -1,17 +1,23 @@ // Copyright 2017-2021 @polkadot/util authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { objectKeys } from './keys'; + +/** + * @name objectSpread + * @summary Concats all sources into the destination + */ export function objectSpread (dest: object, ...sources: (object | undefined | null)[]): T { for (let i = 0; i < sources.length; i++) { const src = sources[i]; if (src) { - const keys = Object.keys(src); + const keys = objectKeys(src); for (let j = 0; j < keys.length; j++) { const key = keys[j]; - (dest as Record)[key] = (src as Record)[key]; + dest[key] = src[key]; } } } diff --git a/packages/util/src/object/values.spec.ts b/packages/util/src/object/values.spec.ts new file mode 100644 index 000000000..e18743839 --- /dev/null +++ b/packages/util/src/object/values.spec.ts @@ -0,0 +1,17 @@ +// Copyright 2017-2021 @polkadot/util authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import { objectValues } from '.'; + +describe('objectValues', (): void => { + it('extracts all values', (): void => { + const o = { a: 1, b: 2, c: 3 }; + const values = objectValues(o); + + expect(values).toEqual([1, 2, 3]); + + for (const v of values) { + expect(v).toBeDefined(); + } + }); +}); diff --git a/packages/util/src/object/values.ts b/packages/util/src/object/values.ts new file mode 100644 index 000000000..579f04dea --- /dev/null +++ b/packages/util/src/object/values.ts @@ -0,0 +1,12 @@ +// Copyright 2017-2021 @polkadot/util authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +type Values = T[keyof T][]; + +/** + * @name objectValues + * @summary A version of Object.values that is typed for TS + */ +export function objectValues (obj: T): Values { + return Object.values(obj) as Values; +}