Kunal Jain
Kunal Jain

Reputation: 61

How to write a function type to access nested key of object in typescript

I'm trying to write a function that will accept 2 parameters i.e key and subkey and return one of the properties of that nested object. I have successfully written the type for function but cannot access the property for the same.

This is what my code looks like:

type ObjectDefinationType<T> = {
  myFunction: () => void;
  data?: T[];
  someData: string;
};

type KeySet1 = "key1" | "key2";
type KeySet2 = "key3" | "key4";

type DataType1 = {
  id: string;
  num: number;
};

type DataType2 = {
  age: number;
  address: string;
};

type KeySet1Record = Record<KeySet1, ObjectDefinationType<DataType1>>;
type KeySet2Record = Record<KeySet2, ObjectDefinationType<DataType2>>;

type SetStoreType = {
  set1: KeySet1Record;
  set2: KeySet2Record;
};

const initialData = {
  myFunction: () => {},
  someData: "someData"
};
const set1: KeySet1Record = {
  key1: { ...initialData },
  key2: { ...initialData }
};
const set2: KeySet2Record = {
  key3: { ...initialData },
  key4: { ...initialData }
};

const setStore: SetStoreType = {
  set1,
  set2
};

const myFunc = <T extends keyof SetStoreType, K extends keyof SetStoreType[T]>(
  key: T,
  subKey: K
) => {
  // This should also work
  console.log("I want to access data", setStore[key][subKey].someData);

  // This will work but I dont want this:
  // setStore[key][subKey] = {
  //   ...setStore[key][subKey],
  //   myFunction: () => {
  //     // This is some function
  //   }
  // };

  // This should work:
  setStore[key][subKey].myFunction = () => {
    // This is some function
  };
};

I am not sure why I am not able to access

myFunction property from an object

I have created a code sandbox for the same Code sandbox

Upvotes: 0

Views: 716

Answers (2)

Okan Aslan
Okan Aslan

Reputation: 174

Instead of using generic types you can use the actual types.

type KeysOfUnion<T> = T extends T ? keyof T : never;
const myFunc = (key: keyof SetStoreType, subKey: KeysOfUnion<SetStoreType[keyof SetStoreType]>) => {
    setStore[key][subKey].myFunction = () => {
        // This is some function
    };
    console.log("I want to access data", setStore[key][subKey].someData);
};

I got the small trick to get key of union from here.

Upvotes: 0

JamesK
JamesK

Reputation: 196

I'm not smart enough with Typescript to figure out why what you want to do does not seem to be working, but you could work around this behavior by using a helper function employing type-fest's Get utility type and Lodash's get function like so: https://codesandbox.io/s/compassionate-sammet-w4hr53?file=/src/App.tsx

Not sure if that is usable for whatever it is that you need, but it's the best I could come up with.

Upvotes: 1

Related Questions