vince
vince

Reputation: 8306

Is it possible to use one parameter's type for another parameter?

Let's say I have a function for dispatching an update to a store:

updateData<T>(entity: T, prop: keyof T, value: any): void {
  const action: Action = new SaveAction(entity, {[prop]: value});
  store.dispatch(action);
}

In the example, let's assume T is a class representing a question, which looks something like this:

class Question {
  readonly content: string;
  readonly answer: string;
  readonly score: number;

  constructor(obj: Stringified<Question>) {
    this.content = obj.content;
    this.answer = obj.answer;
    this.score = obj.score;
  }
}

Is it possible to make this function more type-safe by ensuring that the value parameter only accepts values with the type corresponding to the property?

Using the above example, I'd like the TSLint or the Typescript compiler to save me from doing something like

updateData<Question>(someQuestion, 'score', 'some string');

Upvotes: 0

Views: 37

Answers (1)

jcalz
jcalz

Reputation: 330086

I think what you're looking for is:

updateData<T, K extends keyof T>(entity: T, prop: K, value: T[K]): void {
  const action: Action = new SaveAction(entity, {[prop]: value});
  store.dispatch(action);
}

where the value parameter uses a lookup type to constrain it to the relevant property type for that key. And you just call it without explicitly specifying the type parameter (leave off the <Question>):

updateData(someQuestion, 'score', 123); // okay
updateData(someQuestion, 'score', 'some string'); // error: 
// Argument of type '"some string"' is not assignable to parameter of type 'number'.

Hope that helps; good luck!

Upvotes: 1

Related Questions