0

Assuming I have an interface like:

interface Foo {
  description: string;
  amount: number;
}

And a function to update Foo like:

public updateFoo(key: keyof Foo, val: string | number): void {
  this.foo = { ...foo, [key]: val }
}

When I call this function in TypeScript, this is obviously considered valid:

this.updateFoo('description', 10)

Is there a way for TypeScript to use the keys that it already knows belong to the target interface and validate the type of the second argument being passed?

1 Answer 1

2

Yes, you want to use a generic function:

 public updateFoo<K extends keyof Foo>(key: K, val: Foo[K]): void {        
    this.foo = { ...this.foo, [key]: val };
    // or just this.foo[key] = val;
  }

The key parameter is a generic type K constrained to keyof Foo, and the val parameter is the lookup type Foo[K], meaning "the type of the property of Foo whose key is of type K". This allows you to do the sort of type-safe property getting and setting that you're looking for.

Now if you try the offending code you get an error:

this.updateFoo('description', 10) // error, 10 not assignable to string

Hope that helps. Good luck!

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

1 Comment

The reason I don't say this.foo[key] = val is to avoid mutations, I don't actually access the foo property directly it was just for the sake of brevity. I never knew Foo[K] was valid syntax, this is awesome.

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.