如果数组的每个元素都是一个函数,如何合并数组中的元素?

时间:2018-11-07 10:07:17

标签: typescript

TestDrive:

现在我像这样应用上面的函数:

export type MakeActionType = (name: string) => {[key: string]: string}
const combineActionType = <AT extends (MakeActionType | undefined)[]>(...actionTypeList: AT) => (name: string) => {
    return actionTypeList.reduce(
        (previous, makeActionType) => {
            const actionType = makeActionType ? makeActionType(name) : {}
            return {
                ...previous,
                ...actionType,
            }
        },
        {}
    )
}

我希望const abAction = combineActionType((name) => ({a: 'a'}), (name) => ({b: 'b'})) const ab = abAction('ab') 包含aba属性,但是b返回ab类型,这就是{}或{ {1}}无效。

ab.a

如何定义同时包含'a'和'b'属性的ab类型?

1 个答案:

答案 0 :(得分:1)

您需要明确告诉打字稿reduce的返回类型是什么,打字稿将无法推断出该类型。

返回类型应该是所有函数返回类型的交集。我们可以使用类型查询(AT[number])获得函数类型的并集,并可以使用ReturnType条件类型获取返回类型。要将返回类型的并集转换为交集,我们可以使用here中的UnionToIntersection类型(别忘了对jcalz进行投票)

type UnionToIntersection<U> = 
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
export type MakeActionType = (name: string) => { [key: string]: string }
const combineActionType = <AT extends (MakeActionType | undefined)[]>(...actionTypeList: AT) => (name: string)  => {
    return actionTypeList.reduce(
        (previous, makeActionType) => {
            const actionType = makeActionType ? makeActionType(name) : {}
            return {
                ...previous,
                ...actionType,
            }
        },
        {} 
    )  as UnionToIntersection<ReturnType<Exclude<AT[number], undefined>>>
}


const abAction = combineActionType((name) => ({a: 'a'}), (name) => ({b: 'b'}))
const ab = abAction ('a') // { a: string } & { b: string }

Playground link