0

I want to update the student state correctly, a student is an object that contains user, city and grades objects. I can do it in the updateStudent function, but the parameter data is not strict and has a type any.

I want to restrict the parameter data to IUser | ICity | IGrade, what would be the best procedure for this case?

interface IUser {
  name?: string;
  id?: number;
}
interface ICity {
  city?: string;
  zip?: number;
}
interface IGrade {
  math?: string;
  biology?: string;
}

interface IStudent {
  user: IUser;
  city: ICity;
  grades: IGrade;
}


const [student, setStudent] = useState<IStudent>({
  user: {},
  city: {},
  grade: {},
});


const updateStudent = (data: any, key: string) => {
  setStudent({ ...student, [key]: data });
};

1 Answer 1

2
const updateStudent = <S extends IStudent, K extends keyof S>(data: S[K], key: K) => {
  setStudent({ ...student, [key]: data });
};

Solution is to use two generic types: S and K. data argument is defined as type of value for key K, and key represents K. TypeScript is able to inference both types without any type annotation during calling the function.

Two generic types are crucial, as this is the way how to inform that we have relation between two arguments.data: S[K], key: K, data will represented as type of value picked by key.

One thing to add, because the key defines the data, and not the other way around, better would be to have first argument as key and second as data.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.