E
E
Evgeny2019-09-01 10:44:56
OOP
Evgeny, 2019-09-01 10:44:56

How to get the type returned by the result function in TS?

The runAgents function takes a dict with a class that has a parse() method
and returns a dict with the results of the function.
How to declare the result type (IAgentsResult) of the runAgents function so that TS itself substitutes the correct types depending on the input type?

export interface IAgentList {[key: string]: IAgentBase<any>}

export interface IAgents extends IAgentList {
    items?: IItemsParser;
    page?: IPageParser;
    parser?: IWebParser;
}

export interface IAgentBase<T> {
    parse(): Promise<T>;
}

export interface IItemsParser extends IAgentBase<IItem[]> {
}

export interface IPageParser extends IAgentBase<IDataSet[]> {
}

export interface IWebParser extends IAgentBase<any> {
}

export interface IAgentsResult<T> {
    items?: IItem[];
    page?: IDataSet[];
    parser?: any;
}

// в реальности все иначе, написал для понимания желаемого результата
async function runAgents<T extends IAgentList>(agents: IAgentList): Promise<IAgentsResult<T>> {
    const result: IAgentsResult<T> = {};
    Object.keys(agents).forEach(
      async key => result[key] = await agents[key].parse()
    );
    return result;
}

const agents : IAgents = {...}
const result = runAgents(agents)

Answer the question

In order to leave comments, you need to log in

2 answer(s)
I
Interface, 2019-09-01
Lubyanoy @arswarog

If I understood everything correctly, then the runAgents signature should become something like:
where ResolveResult:

type ResolveResult<T extends IAgentList> = {
    [key in keyof T]: T[key] extends IAgentBase<infer R> ? R : never;
}

Solution based on infer from TS 2.8: https://www.typescriptlang.org/docs/handbook/relea...
All code (slightly modified):
spoiler
type IItem = {type: 'IItem'};
type IDataSet = {type: 'IDataSet'};
export type IAgentList = {
    [key: string]: IAgentBase<any>;
}

export interface IAgents extends IAgentList {
    items: IItemsParser;
    page: IPageParser;
    parser: IWebParser;
}

export interface IAgentBase<T> {
    parse(): Promise<T>;
}

export interface IItemsParser extends IAgentBase<IItem[]> {
}

export interface IPageParser extends IAgentBase<IDataSet[]> {
}

export interface IWebParser extends IAgentBase<any> {
}

export interface IAgentsResult<T> {
    items?: IItem[];
    page?: IDataSet[];
    parser?: any;
}

type ResolveResult<T extends IAgentList> = {
    [key in keyof T]: T[key] extends IAgentBase<infer R> ? R : never;
}

// в реальности все иначе, написал для понимания желаемого результата
async function runAgents<T extends IAgentList>(agents: T): Promise<ResolveResult<T>> {
    const result: ResolveResult<T> = {} as any;
    Object.keys(agents).forEach(
      async key => result[key as keyof T] = await agents[key as keyof T].parse()
    );
    return result;
}

async function main() {
    const agents : IAgents = {} as any;
    const result = await runAgents(agents)
    result // typed
}

S
Stanislav Makarov, 2019-09-01
@Nipheris

return type

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question