Search code examples
typescriptfunctionarrow-functions

How to change return type based on optional object parameter


How to create { a: boolean } only if aX exist in the obj parameter

type IObjFunc = () => void

interface IObj {
    aX?: IObjFunc
    bX?: IObjFunc
    cX?: IObjFunc
}

interface IReturnData {
    a?: boolean
    b?: boolean
    c?: boolean
}

const func = (obj: IObj) => {
    const returnData: IReturnData = {}

    if (obj.aX)
        returnData.a = true
    
    if (obj.bX)
        returnData.b = true
    
    if (obj.cX)
        returnData.c = true

    return returnData
}

const test1 = func({ aX: () => undefined })

console.log(test1.a) // Pass
console.log(test1.b) // No error, should be error

Playground


Solution

  • Modify your IReturnData to be generic if input

    type IReturnData<T extends IObj> = {
        [K in keyof T
          as K extends `${infer P}X` ? P // or another mapping expression of your choice, like `ReturnMapping[K]`
          : never
        ]-?: boolean;
    } & unknown // <- makes generic unwrap immediately
    

    and make your function generic as

    const func = <T extends IObj>(obj: T): IReturnData<T> => {...}
    

    Playground: https://tsplay.dev/mLvOAw