1

Sorry about the vague wording of the question.

Let's say I have a type like this:

type TestObject = {
  arr: Array<{x: number, y: Array<{z: string}}>>;
  obj: {[key: string]: number;
}

I'd like to be able to enforce that paths are valid - ideally at compile time, but runtime would be okay, along these lines:

function setValue<T>(object: T, path: string, value: unknown) {
  // perform the set operation
}

My intention is that the following should work:

const o: TestObject = { arr: [], obj: {} };
setValue<TestObject>(o, "arr[0].x", 1);
setValue<TestObject>(o, "arr[0].y[2].z", "hello world");
setValue<TestObject>(o, "obj['x']", 1);

But if you tried this, it should fail, as there is no TestObject.a:

setValue<TestObject>(o, "a", 1);

Ideally this would be implemented in such a way that the developer would get Intellisense and errors in the IDE, but a runtime solution would be okay as well.

Radu Diță
  • 13,476
  • 2
  • 30
  • 34
Scott Schafer
  • 487
  • 3
  • 14
  • I think it's impossible for your case because the string is a type itself, and the compiler cannot predict your string path as a type – Nick Vu Jun 29 '22 at 02:40
  • Have you tried `setValue((o, "obj[0]", {"k":1}` this? – ClassHacker Jun 29 '22 at 02:47
  • 1
    There is no way TS can read a string path but maybe `lodash.get` https://lodash.com/docs/4.17.15#get or `ramda.path` https://ramdajs.com/docs/#path could be of help to this use case for the runtime. – 3Dos Jun 29 '22 at 06:17
  • 1
    I believe your question is a duplicate of [this](https://stackoverflow.com/questions/68668055/eliminate-nevers-to-make-union-possible/68672512?noredirect=1#comment121362429_68672512), at least it very close. However, you can check [my](https://catchts.com/deep-pick) article – captain-yossarian from Ukraine Jun 29 '22 at 06:18
  • 1
    Other answers that might be relevant: [this](https://stackoverflow.com/questions/67242871/declare-a-type-that-allows-all-parts-of-all-levels-of-another-type#answer-67247652), [this](https://stackoverflow.com/questions/68668055/eliminate-nevers-to-make-union-possible/68672512?noredirect=1#comment121362429_68672512), [this](https://stackoverflow.com/questions/69449511/get-typescript-to-infer-tuple-parameters-types/69450150#69450150) and [this](https://stackoverflow.com/questions/69126879/typescript-deep-keyof-of-a-nested-object-with-related-type#answer-69129328) – captain-yossarian from Ukraine Jun 29 '22 at 06:20
  • 1
    xIf you want to handle square bracket notation like `arr[0]`, I can update the answer – captain-yossarian from Ukraine Jun 29 '22 at 06:21

1 Answers1

0

TS doesn't allow for checking properties that come as strings.

The way you have setup your TestObject it will complain that you don't have an index type defined on it when you'll try to access properties using string indexes.

Radu Diță
  • 13,476
  • 2
  • 30
  • 34