Micaël Félix
Micaël Félix

Reputation: 2775

flow javascript generic type " Cannot reference type `CustomType` [1] from a value position."

I am trying to call an async function and specify a custom type (let's call it "CustomType"). I've specified a few random properties in that type, it's just to understand that it's something that comes from a database (content could vary depending on the retrieved item, I have many different "CustomType" for each kind of file stored in a NoSql database).

This is the code testable by using https://flow.org/try

/* @flow */

// Type that would be returned in the case of usage of "mySpecificCallFunc(): Promise<Array<CustomType>>" defined below
declare type CustomType = { 
  prop1: boolean,
  prop2: string,
  prop3: Date
}

// Generic function that does the hard work
async function asyncFunc<T>(dateStart: Date, otherArgument: string):Promise<Array<T>>
{
  let r:Array<T> = [] // do a call that returns an array that must be of a specific type
  return r
}

// High level function that would send parameters to the generic function "asyncFunc"
async function mySpecificCallFunc(): Promise<Array<CustomType>>
{
  let r = await asyncFunc<CustomType>(new Date(), 'test')
  return []
}

Cannot reference type CustomType [1] from a value position.

Flow does not want the custom type to be used.

In C# this kind of generic usage would be totally acceptable so I do not understand why it is complaining?

It gives the following error :

20:   let r = await asyncFunc<CustomType>(new Date(), 'test')
          ^ Cannot compare boolean [1] to string [2].
References:
20:   let r = await asyncFunc<CustomType>(new Date(), 'test')
          ^ [1]
20:   let r = await asyncFunc<CustomType>(new Date(), 'test')
                                      ^ [2]
20:   let r = await asyncFunc<CustomType>(new Date(), 'test')
                          ^ Cannot reference type `CustomType` [1] from a value position.
References:
3: declare type CustomType = {
            ^ [1]

UPDATE: There is currently no link between "CustomType" and the request arguments. In the real world scenario, it looks like this :

call: DbRetrieve('type1', param1, param2)
return: [{ _type: 'type1', prop1: true, prop2:'b' }] // an array containing <CustomType> objects

As you can see, there's no "shape" that can be defined from the arguments of the function asyncFunc because the arguments are not always linked to the properties of the returned object.

It's an ORM-like call, I just wanted to be able to specify the type without doing some "brute cast", but I may be following the wrong path because the type cannot be inferred from the usage...

Upvotes: 1

Views: 8212

Answers (1)

Kirill Glazunov
Kirill Glazunov

Reputation: 497

  1. You can not specifying type directly on call.
  2. Your CustomType is an object, but in code you expect a boolean

So, first of all you need to make a link between an incoming and outgoing data:

async function asyncFunc<T>(p: T):Promise<T[]> {
  return []
}

<T> in the function declaration is just like declaring a variable, but p: T and :Promise<T[]> make a dependency

Second, you need to make the T a little bit narrow by async function asyncFunc<T: CustomType>.... And change your type CustomType = boolean;

After that, you just need to call await asyncFunc(true); without any typing.

UPD:
You trying to specify a type the function should return, just on the function call - it`s not a right way not on flow and not on JS at all. A function result type should be certainly declared on the function declaration point - it may be a single type of several types combination (type0 | type).

Generic types is used to make a relations between parameters and result. So, you can, for example, make a function that get a param and returns an array of same types values like function doSmt<T>(a: T): T[] {return [a];}

I`m not sure what exactly you trying to do, but maybe you need something like this:

type CustomType<A, B> = {
  prop0: A,
  prop1: B,
}
function asyncFunc<C: string, D: number>(foo: C, bar: D): CustomType<C, D> {  
  // some actions
}

Upvotes: 1

Related Questions