Home > OS >  Looking for a better way to structure code
Looking for a better way to structure code

Time:12-25

I have the following

export type TRange = [number, number, string?, string?]

export const splitToken = (
    token: string,
    separator: string = '|',
): string[] | string => {
    if (voca.includes(token, separator)) {
        return voca.split(token, separator)
    }
    return ''
}

update(property: string, path: string, range: TRange) {
        store.update(
            write((state: IPreference) => {
                if (splitToken(path).length === 0) {
                    state[path] = { ...state[path], [property]: range }
                }

                if (splitToken(path).length === 2) {
                    const path0: string = splitToken(path)[0]
                    const path1: string = splitToken(path)[1]

                    state[path0][path1] = { ...state[path0][path1], [property]: range }
                }

                if (splitToken(path).length === 3) {
                    const path0: string = splitToken(path)[0]
                    const path1: string = splitToken(path)[1]
                    const path2: string = splitToken(path)[2]

                    state[path0][path1][path2] = {
                        ...state[path0][path1][path2],
                        [property]: range,
                    }
                }
            }),
        )
    }


I am looking for a better way to generate the final path in the write() function above eg

state[path0][path1][path2][..n]

The above works but it just does not scales very well.

CodePudding user response:

I would suggest to follow this path:

update(property: string, path: string, range: TRange) {
  const steps = splitToken(path);

  // We leave this case as it was originally in your code
  if (!steps.length) {
    state[path] = { ...state[path], [property]: range };
    return;
  }

  // We split the steps to achieve the branch of the object you need, leaving the last one aside.
  const addressSteps = steps.slice(0, -1);
  const lastStep = addressSteps[addressSteps.length - 1];

  // We get to the branch you need to update
  const stateBranch = addressSteps.reduce((final, step) => final[step], state);
  stateBranch[lastStep] = {...stateBranch[lastStep], [property]: range};
}

CodePudding user response:

Another example using a plain old for loop to update the original object.

function update(state: any, path: string, value: any): any {
    const parts = path.split('|');
    setState(state, parts, value);
}

function setState(state: any, parts: string[], value: any) {
    let statePointer = state;
    for (let i = 0; i < parts.length - 1; i  = 1) {
        if (typeof statePointer[parts[i]] !== 'object') {
            statePointer[parts[i]] = {}; // sets or overwrites any other value than 'object'
            // ... or throw exception depending on your requirements
        }
        statePointer = statePointer[parts[i]];
    }

    statePointer[parts[parts.length-1]] = value;
}

const preferences = {
    'foo': {
        'bar': true,
    }
}

update(preferences, 'foo|bazz|password', 'hunter2');

console.log(JSON.stringify(preferences, null, 2));

Output:

{
  "foo": {
    "bar": true,
    "bazz": {
      "password": "hunter2"
    }
  }
}
  • Related