-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Description
Here is a basic User class:
class User< U > {
private _user: Partial< U > = {};
public set< K extends keyof U >(
key: K,
val: U[ K ],
) : void {
this._user[ key ] = val;
}
}And a basic Employee interface:
interface Employee {
name: string;
city: string;
role: number;
}Now, consider the following implementation:
const admin = new User< Employee >();
admin.set( "name", 10 );The above script yields the following error which is expected.
Argument of type 'number' is not assignable to parameter of type 'string'.
Now take a look at the following implementation:
const admin = new User< Employee >();
admin.set< "name" | "role" >( "name", 10 );The above script does not yield any error and it is also expected, as long as 10 is assignable to name or role.
To make it more clear, let's take a look at the following script:
const admin = new User< Employee >();
admin.set< "name" | "role" >( "name", true );The above script yields the following error which is also expected.
Argument of type 'boolean' is not assignable to parameter of type 'string | number'.
Now, what I want to achieve is, 10 should not be allowed to be stored as a value of name at any mean.
For this, I need to make some changes to my code something similar to the followings:
public set< K extends keyof U >(
key: K,
val: U[ valueof key ],
) : void {
this._user[ key ] = val;
}But as long as there is nothing like valueof key, this cannot be achieved dynamically.
For testing, if you replace U[ K ] by U[ "name" ], you will see 10 is no longer allowed anymore at any form.
Many programmers solved similar problems by applying T[ keyof T ] which I think is not applicable to this case.
Thanks in advance.