Home > front end >  Is it possible to dynamically determine the type by the name of the object's proxy key in TypeS
Is it possible to dynamically determine the type by the name of the object's proxy key in TypeS

Time:01-26

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;
  }
}

Playground Link

  • Related