Reputation: 43
Let's say I have this generic flow type:
/* @flow */
type Cat<T> = {
get:()=>T
};
And I want to create a function that creates a cat:
const makeCat:<U>(getter:()=>U)=>Cat<U>
= (getter) => ({get:getter});
Flow gives me the following error:
Cannot assign function to `makeCat` because `U` [1] is incompatible with `U` [2] in the return value of property `get` of the return value.
I've tried several different ways to define the types of the passed in 'getter', but it's always the same error.
Upvotes: 1
Views: 337
Reputation: 5801
Based on the answer by @kindaro, but simplified to not having to define the intermediary function type, by simply using the regular "old-school" function declaration form:
type Cat<T> = { get: () => T };
function makeCat<U>(getter: () => U): Cat<U> {
return { get: getter };
}
// inferred as Cat<string>
const cat: Cat<string> = makeCat(() => 'secret');
// const cat: Cat<number> = makeCat(() => 'secret'); // Yields error
// inferred as string
const value: string = cat.get();
// const value: number = cat.get(); // Yields error
Upvotes: 0
Reputation: 12008
Try this. I broke up the logic of it in to a few extra steps to make it more understandable. The key part of this solution is using *
to tell flow to "fill in the blanks" whenever the makeCat
function is being used.
type Cat<T> = {
get: () => T
}
// define signature of "makeCat" function
type MakeCat<U> = (getter: () => U) => Cat<U>
// use * to infer the variable at usage
const makeCat: MakeCat<*> = getter => ({ get: getter })
// inferred as Cat<string>
const cat = makeCat(() => 'secret')
// inferred as string
const value = cat.get()
Upvotes: 2