I am writing a wrapper class that will contain functions for interacting with the user entity, such methods as checking that the user is a guest, functions for checking his permissions, etc. and one of the methods I want to make an accessor to its fields like name, email, id. And I had the idea that the accessor would return me data from the user himself by the name of the field in the entity. Here is the code I have and the comments to it that I want to change:
export interface UserModel {
id: number
name: string
email: string
}
export class User {
constructor(private _user: UserModel | null) {
}
// I can return the type I need through the generic, but I would like to be able to analyze the key that is in the UserModel model using the name parameter
public get<T>(
// This works great for me, autocomplete only lets me enter id,name,email
name: keyof UserModel
): T {
if (this._user === null) {
throw new Error("User is empty.")
}
// And finally, instead of the generic T, I would like something like as UserModel[name]
return this._user[name] as T
}
public isGuest(): boolean {
return this._user === null;
}
}
Is it possible to arrange this so that when I use the get
method of an instance of the User
class for example:
const user = new User({...})
// The typescript told me that the string type would be returned to me instead of using the generic type get<string>('email')
user.get('email') // return type string
user.get('id') // return type number
CodePudding user response:
You just need to capture the type of the key that is passed in using a generic type parameter. You can then use it to index into UserModel
to get the actual type of the key passed in:
export class User {
constructor(private _user: UserModel | null) {
}
public get<K extends keyof UserModel>(
name: K
): UserModel[K] {
if (this._user === null) {
throw new Error("User is empty.")
}
return this._user[name]
}
public isGuest(): boolean {
return this._user === null;
}
}