I am currently enhancing TypeScript usage in a project by implementing generics. The challenge I am facing involves dealing with a complex object retrieved from the backend, which consists of a class with numerous attributes, most of which are classes themselves. In our form, we have a common change handler that currently contains a few instances of any
to make it functional, but my goal is to enhance it using generics.
This code snippet provides a simplified version of the structure in my application, showcasing the same issues I encounter:
class PhoneNumber {
prefix: number;
exchange: number;
line: number;
}
class Address {
address1: string;
address2: string;
city: string;
}
class User {
phone: PhoneNumber;
address: Address;
}
const user = new User();
function setValue<A extends keyof User, T extends User[A], K extends keyof T, V extends T[K]>(
value: V,
fieldType: new () => T,
fieldName: A,
fieldAttribute: K
) {
if (!user[fieldName]) {
user[fieldName] = new fieldType();
}
const field = user[fieldName];
// error here.
field[fieldAttribute] = value;
}
setValue(408, PhoneNumber, 'phone', 'prefix');
I've attempted various approaches, and the closest solution I have reached exhibits the use of sane values for the generics during the function call at the end in my IDE:
function setValue<"phone", PhoneNumber, "prefix", number>()
. However, I encounter a compilation error:
TS2536: Type 'K' cannot be used to index type 'User[A]'.
Am I approaching this problem incorrectly? If I'm unable to resolve this issue, I may resort to segregating the different types into separate handlers as an alternative.
Furthermore, there's a scenario where some of the fields are arrays of objects, further complicating the situation.