Skip to content

Commit

Permalink
Remove lodash get
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewMusgrave committed Feb 28, 2019
1 parent 7f14b53 commit 33f991c
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/components/AppProvider/utilities/Intl/Intl.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import merge from 'lodash/merge';
import get from 'lodash/get';
import {autobind} from '@shopify/javascript-utilities/decorators';
import get from '../../../../utilities/get';
import defaultTranslation from '../../../../locales';
import {
TranslationDictionary,
Expand Down
2 changes: 1 addition & 1 deletion src/components/AppProvider/utilities/Intl/translate.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import get from 'lodash/get';
import {get} from '../../../../utilities/get';
import {
TranslationDictionary,
PrimitiveReplacementDictionary,
Expand Down
2 changes: 1 addition & 1 deletion src/test-utilities/enzyme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import {
ShallowRendererProps,
} from 'enzyme';
import * as React from 'react';
import get from 'lodash/get';
import merge from 'lodash/merge';
import {get} from '../utilities/get';
import {PolarisContext} from '../components/types';

// eslint-disable-next-line shopify/strict-component-boundaries
Expand Down
4 changes: 4 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,3 +242,7 @@ export const contentContextTypes: ValidationMap<any> = {
export interface WithContextTypes<IJ> {
context: IJ;
}

export interface GeneralObject {
[key: string]: any;
}
32 changes: 32 additions & 0 deletions src/utilities/get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {GeneralObject} from '../types';

const OBJECT_NOTATION_MATCHER = /\[(.*?)\]|(\w+)/g;

export function get<T>(
obj: GeneralObject | undefined,
keypath: string | string[],
defaultValue?: T,
): T | any {
if (obj == null) return undefined;

const keys = Array.isArray(keypath) ? keypath : getKeypath(keypath);
let acc = obj;
for (let i = 0; i < keys.length; i++) {
const val = acc[keys[i]];
if (val === undefined) return defaultValue;
acc = val;
}

return acc;
}

function getKeypath(str: string) {
const path = [];
let result: RegExpExecArray | null;
while ((result = OBJECT_NOTATION_MATCHER.exec(str))) {
const [, first, second] = result;
path.push(first || second);
}

return path;
}
37 changes: 37 additions & 0 deletions src/utilities/tests/get.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {get} from '../get';

describe('get', () => {
it('returns undefined when the path does not exist', () => {
expect(get({}, 'a')).toBeUndefined();
});

it('returns a value for a single keypath', () => {
expect(get({hello: 'polaris'}, 'hello')).toBe('polaris');
});

it('returns the value for a complex keypath', () => {
expect(get({keyA: {keyB: {keyC: 'polaris'}}}, 'keyA.keyB.keyC')).toBe(
'polaris',
);
});

it('returns undefined when the object is not provided', () => {
expect(get(undefined, 'keyA.keyB.keyC')).toBeUndefined();
});

it('accepts a array of keys for keypath', () => {
expect(
get({keyA: [{keyB: {keyC: 3}}]}, ['keyA', '0', 'keyB', 'keyC']),
).toBe(3);
});

it('accepts string keypath with square bracket notation', () => {
expect(get({keyA: [{keyB: {keyC: 3}}]}, 'keyA[0].keyB.keyC')).toBe(3);
});

it('returns the default value for undefined results', () => {
expect(
get({keyA: [{keyB: {keyC: 3}}]}, ['keyA', '0', 'keyB', 'keyC', 'not']),
).toBeUndefined();
});
});

0 comments on commit 33f991c

Please sign in to comment.