Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to return type based on array fields type

const record = await OrderModel.read(1003, [
  'id', 
  'billing_name',
]);
##record type object should provide record.id or record.billing_name only

the OrderModel class already has a generic OrderType (T) with all the fields available in that table.

What I’m trying to do is infer the type of record with only the keys defined in the second argument (fields).

Currently, all keys of OrderType are available and I can’t seem to implement the Pick utility correctly to get the correct type returned.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

// from OrderModel.ts
  public async read(id: number, fields: (keyof T)[] = [])
  {
    const result = await this.database.read<T, typeof fields>(id, this.tableName, fields);
    return result;
  }

// from database adaptor (this.database above)
  public async read<T, K extends (keyof T)>(id: number, tableName: string, fields: K[]): Promise<Pick<T, K>>
  {
    return this.connection(tableName).select(fields).where('id', id).first();
  }
// OrderType
export interface OrderModel {
  id: number;
  billing_name: string;
  billing_email: string;
  ...
}

>Solution :

You should apply the same generic type logic as your adapter read method, in the OrderModel version. Try something like this:

// notice generic and argument here, as well as return type
public async read<K extends keyof T>(id: number, fields: K[] = []): Promise<Pick<T, K>>
  {
    // notice type change below
    const result = await this.database.read<T, K>(id, this.tableName, fields);
    return result;
  }

See example here, I had to make some changes in order not to implement all the classes, but the gist is the same

Side note: Since you are directly passing the promise, no need to return/await it separately, just return it immediately:

public async read<K extends keyof T>(id: number, fields: K[] = []): Promise<Pick<T, K>>
  {
    return this.database.read<T, K>(id, this.tableName, fields);
  }
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading