admin管理员组

文章数量:1406926

I've been looking at adding Flow to my javascript project.

In several cases, I do something like this, I have an object.

const myObject = {
    x: 12,
    y: "Hello World"
}

And I have a general function that does some mapping on the object, keeping the keys but replacing the values.

function enfunctionate(someObject) {
   return _.mapValues(myObject, (value) => () => value)
}

I'd like the function to return the type {x: () => number, y: () => string} Is there a way to make this happen?

Of course, I could type it more generically as {[key: string]: any} but I'd lose a lot of the static typing I'd like to gain by using flow.

If I could replace my few cases that do this with code generation or macros that could work, but I don't see a good way to do that with flow.

Is there a way to solve this problem?

I've been looking at adding Flow to my javascript project.

In several cases, I do something like this, I have an object.

const myObject = {
    x: 12,
    y: "Hello World"
}

And I have a general function that does some mapping on the object, keeping the keys but replacing the values.

function enfunctionate(someObject) {
   return _.mapValues(myObject, (value) => () => value)
}

I'd like the function to return the type {x: () => number, y: () => string} Is there a way to make this happen?

Of course, I could type it more generically as {[key: string]: any} but I'd lose a lot of the static typing I'd like to gain by using flow.

If I could replace my few cases that do this with code generation or macros that could work, but I don't see a good way to do that with flow.

Is there a way to solve this problem?

Share Improve this question asked Sep 18, 2016 at 0:10 Winston EwertWinston Ewert 45.1k10 gold badges69 silver badges86 bronze badges 2
  • As u can see here docs.omniref./js/npm/lodash-node/3.1.0/symbols/_.mapValues mapValues accepts any and returns a copy so you cannot keep it in type. – Hitmands Commented Sep 27, 2016 at 5:23
  • Possible duplicate of How do I type a function with input and output objects with the same keys but different value types? – Winston Ewert Commented Oct 1, 2016 at 15:10
Add a ment  | 

2 Answers 2

Reset to default 6 +100

This is the best you can get at the moment, while it's safer than {[key: string]: any} there's still an any involved

function enfunctionate<O: Object>(someObject: O): { [key: $Keys<O>]: (...rest: Array<void>) => any } {
   return _.mapValues(someObject, (value) => () => value)
}

const obj = enfunctionate(myObject)

obj.x() // ok
obj.unknown() // error

EDIT: starting from v.33 you can use $ObjMap

function enfunctionate<O>(o: O): $ObjMap<O, <V>(v : V) => () => V> {
  return _.mapValues(o, (value) => () => value)
}

Flow is able to infer a lot of things. However, if you want to pin the types, then you have to create the types yourself. You need to create a type for the object you are passing to enfunctionate and then specify the type that is returned.

You can type the function with type alias. So, you can create a new explicit type for that function.

function enfunctionate<X, Y>(x: X): Y {
    return _.mapValues(myObject, (value) => () => value)
}

As long as you know the type of X, then you know the type of Y. Type aliasing, generics, and unions should be able to give you flexibility you need.

However, I'm also thinking as long as the type of mapValues is specified well (hopefully by someone else) then you can get away with just specifying the type that enfunctionate takes and let Flow infer the return type of that function.

本文标签: javascriptFlow types on objectsStack Overflow