将T的数组键入为T

时间:2019-09-29 07:25:04

标签: typescript typescript-typings

我正在尝试将参数的结果映射到回调,而我正在努力在TypeScript中键入该结果。 我具有以下功能:

type CustomRouteType<TParam = any> = <T>(value?: T) => TParam;
const createRoute = <TTypes extends CustomRouteType[]>
    (dictionary: RouteDictionary<TTypes>,
    callback: (...params: TTypes) => void) => {

    // Logic Here
}
createRoute(
    route`/api/someEndpoint/${Number}/${String}/test`, 
    (p1, p2) => {

});

route函数将字符串文字转换为自定义字典,该字典公开了路由中的参数,因此我无法预先知道route函数可能返回的类型。 在示例中,这将返回RouteDictionary <[NumberConstructor,StringConstructor]>,而我在回调中设置p1和p2的方式就是那些构造函数,我想将这些参数映射为那些构造函数的ReturnValue类型

Typescript仅具有ReturnValue而没有ReturnValues,如何映射这些类型,以便回调函数的参数推断出我正在寻找的返回类型?

供参考:

class RouteString { 
    constructor(public routeString: string) { } 
}
class RouteParameter<T = any> { 
    constructor(public routeString: CustomRouteType<T>) { } 
}

type RouteDictionary<TTypes extends CustomRouteType[]> = {
    routeParts: (RouteString | RouteParameter)[]
    types: TTypes
}

const route = <TParams extends any[], TTypes extends CustomRouteType<any>[]>
    (template: TemplateStringsArray, ...keys: TTypes): RouteDictionary<TTypes> => {

    let routeParts: (RouteString | RouteParameter)[] = [];
    const stringParts = template.raw || [];

    for (let partIndex = 0; partIndex < stringParts.length; partIndex++) {
        const part = stringParts[partIndex];
        const stringChunks = part.split('/').filter(chunkPart => chunkPart !== String())

        routeParts = [... routeParts, ...stringChunks.map(chunk => new RouteString(chunk))]

        if (keys.length === 0) continue
        if (keys.length < partIndex) continue

        const routeParam = keys[partIndex]
        if (!routeParam) continue

        routeParts = [...routeParts, new RouteParameter(routeParam)]
    }

    return {
        routeParts,
        types: keys
    };
}

1 个答案:

答案 0 :(得分:2)

您可以使用映射类型将函数的元组映射到返回值的元组:

type ReturnValuesOf<T extends Array<(...a: any[]) => any>> = {
  [P in keyof T]: T[P] extends (...a: any[]) => any ? ReturnType<T[P]> : never
}
type RouteDictionary<T> = T 
type CustomRouteType<TParam = any> = <T>(value?: T) => TParam;
const createRoute = <TTypes extends CustomRouteType[]>
    (dictionary: RouteDictionary<TTypes>,
    callback: (...params: ReturnValuesOf<TTypes>) => void) => {

    // Logic Here
}

function route<T extends any[]>(s: TemplateStringsArray, ...arr: T) :T {
  return arr;
}
createRoute(    
    route`/api/someEndpoint/${Number}/${String}/test`, 
    (p1, p2) => { // p1 number, p2: string 

});