0
votes

Playground is here

I am trying to define a generic type-safe setter function in Typescript. Something like the following:

 type A = {a1: string, a2: number}
 let a: A = {a1: 'foo', a2: 42};
 setPropertyOnA('a1', 42);    // this should fail to type-check
 setPropertyOnA('a2', '43');  // ditto

Below is what I have done (playground link is given above):

type PropType<TObj, TProp extends keyof TObj> = TObj[TProp]; 

type A = {a1: string, a2: number}

let a: A = {a1: 'foo', a2: 42};

function setPropertyOnA(property: keyof A
                      , v: PropType<A, typeof property>): void {

    a[property] = v; // Q1. why is this failing?
}

setPropertyOnA('a1', 42);    // Q2. this should fail to type-check
setPropertyOnA('a2', '43');  // ditto

The PropType utility was copied from here

On the line marked with Q1 I get:

Type 'PropType<A, "a1" | "a2">' is not assignable to type 'never'.
Type 'string' is not assignable to type 'never'.(2322)

On the two lines marked with Q2 I was expecting Typescript to complain, yet it doesn't.

What am I doing wrong?

1

1 Answers

3
votes

That's because you should lock a specific key with generic. Also you can simplify your code without using PropType:

function setPropertyOnA<T extends keyof A>(property: T, v: A[T]): void {
     a[property] = v; // now it works
}

setPropertyOnA('a1', 42);    // it's failed
setPropertyOnA('a2', '43');  // it's failed

Moreover, you can write a function to set property not only to a specific type of object:

function setProperty<T, K extends keyof T>(obj: T, property: K, v: T[K]): void {
     obj[property] = v;
}