How do I enforce a maximum depth and value requirements for a multi-dimensional object containing objects and arrays of primitive (only) values?

37 views Asked by At

Introduction:

I have a multi-dimension object in a TypeScript file, that would look something like this:

const store = {
  key_1: "value",
  key_2: 123,
  key_3: true,
  key_4: {
    key_4_1: "value",
    key_4_2: 123,
    key_4_3: false,
    key_4_4: [
      "value_4_4_1",
      "value_4_4_2",
      "value_4_4_3",
    ]
  },
  key_5: [
    "value_5_1",
    "value_5_2",
    "value_5_3",
  ],
  value_5: {
    key_1: "copy-pasted-from-parent-object",
    key_2: 123,
    key_3: true,
    key_4: {
      key_4_1: "value",
      key_4_2: 123,
      key_4_3: false,
      key_4_4: [
        "value_4_4_1",
        "value_4_4_2",
        "value_4_4_3",
      ]
    },
    key_5: [
      "value_5_1",
      "value_5_2",
      "value_5_3",
    ]
  }
};

Please note that the order, key count, length, value and size of each object and it's child objects/arrays/values can vary from object to object and have no bearing on the final result.

Background:

I want to create an interface or type that enforces the following rules:

  1. Values in arrays and objects (where the value is not an array or another nested object) must be of type number, boolean, or string.
  2. There can never be any undefined, null, or NaN values.
  3. Numbers can never have a negative value (I.E: less than 0).
  4. String values can never be empty.
  5. The object cannot have more than 4 dimensions (4 nested objects).
  6. Arrays will never have nested objects or arrays.
  7. The values of array items will always be of type string.
  8. All keys for all objects must be of type string.

Solution 1 and the outcome:

Here is the interface I've tried to use as the type for this object:

interface Store {
  [key: string]: string | number | boolean | string[] | Store;
}

However, this does not enforce rules 3, 4, or 5.

Solution 2 (for rules 3 and 4) and the outcome:

To simplify the type checking for rules 3 and 4, I've implemented a loop function that checks the values of strings (boils down to string.length > 0 && number >= 0) and used throw new TypeError(...) to notify me of a mistake.

Question:

How do I change this interface or use a better type to enforce these rules in a more efficient way?

0

There are 0 answers