如何在对象中获取keyof函数的包含参数?

时间:2018-10-16 10:59:58

标签: typescript

我有这样的数据

purrr:map_img

如何定义convertData的返回类型

在这种情况下:const data = { inc: (num: number) => num + 1, inc2: (num: number, count = 2) => num + count, } const convertData = <T, K extends keyof T>(_data: T): Record<K, number> => _data const a = convertData(data) a.inc(2) // << wrong, Type 'Number' has no compatible call signatures.

已更新

如果您熟悉ramda,则此示例如下所示

Record<K, number>

没有ramda的示例

let { compose, mapObjIndexed } = require('ramda')
const inc = (n: number) => n + 1
const inc2 = (n: number) => n + 2
const g = {
    inc,
    inc2,
}
const inc3 = (n: number) => n + 3
const g2 = mapObjIndexed((action: any) => compose(inc3, action))(g)


// But in this case g2 is any, so I have to define type of g2.
// How can I define type of g2 depend on the g?

// => So you can use
console.log('>>', g2.inc(2), g2.inc2(5))

在两个示例中,我都想定义g2的类型取决于g。 我该怎么办?

1 个答案:

答案 0 :(得分:1)

我们可以使用映射类型和条件类型来更改对象中每个函数的返回类型:

const inc = (n: number) => n + 1
const inc2 = (n: number, count = 2) => n + count
const g = {
    inc,
    inc2,
}
const inc3 = (n: number) => n + 3


type ChnageReturnType<T, R> = {
    [P in keyof T] : T[P] extends (...a: infer A) => any ? (...a: A) => R: never
} 

type AnyReturnType<T> = {
    [P in keyof T] : T[P] extends (a: any) => infer R ? R: never
}[keyof T]

function mapObject<T, R>(o: T, mapFn: (o: AnyReturnType<T>)=> R) :ChnageReturnType<T, R> {
    return Object.keys(g).reduce(
        (previousValue, key) => {
            console.log('pore', previousValue, key)
            return {
                ...previousValue,
                [key]: (...arg: any[]) => { return inc3(g[key](...arg)) },
            }
        },
    {}) as ChnageReturnType<T, R>
}
const g2 = mapObject(g, inc3)
console.log('>>', g2.inc(2), g2.inc2(5)) // both functions fully typed return numbers

const g3 = mapObject(g, o=> o.toString()) // o is types as number but will be typed to a union of all posible return values ()
console.log('>>', g3.inc(2), g3.inc2(5)) // both functions will return strings 

您也可以只使用ChnageReturnType类型:

const g4: ChnageReturnType<typeof g, number> = Object.keys(g).reduce(
    (previousValue, key) => {
        console.log('pore', previousValue, key)
        return {
            ...previousValue,
            [key]: (...arg: any[]) => { return inc3(g[key](...arg)) },
        }
    },
{}) as any