Flow: Arrow form of generic identity function produces Flow error

Created on 29 Jan 2017  路  3Comments  路  Source: facebook/flow

Flow, a static type checker for JavaScript, version 0.38.0

Perhaps I'm just having one of those days and can't see the woods for the trees.
Nevertheless why does this compile:

function identity<T>(arg: T): T {
  return arg;
}
const id: <T>(arg: T) => T = identity;

but this doesn't?

const identity = <T>(arg: T) => arg;

const id: <T>(arg: T) => T = identity;

Produces:

inconsistent use of library definitions
14:     const identity = <T>(arg: T) => arg;
                                        ^^^ T. This type is incompatible with
16:     const id: <T>(arg: T) => T = identity;
                                     ^^^^^^^^ some incompatible instantiation of `T`

Most helpful comment

I have a similar problem with this. In flow v0.75.0, the following patterns work and they all produce the same type signature: <T> (T) => T (see here)

// @flow

// function with implicit return type
function identity1<T>(x: T) {
  return x;
}

// function with explicit return type
function identity2<T>(x: T): T {
  return x;
}

// function expression with implicit return type
const identity3 = function<T>(x: T) {
  return x;
};

// function expression with explicit return type
const identity4 = function<T>(x: T): T {
  return x;
};

// arrow with implicit return type
const identity5 = <T>(x: T) => x;

// arrow with explicit return type
const identity6 = <T>(x: T): T => x;

console.log(identity1(123), identity1('123'));
console.log(identity2(123), identity2('123'));
console.log(identity3(123), identity3('123'));
console.log(identity4(123), identity4('123'));
console.log(identity5(123), identity5('123'));
console.log(identity6(123), identity6('123'));

But if I try to extract the type signature and use it as a standalone type for the function, it fails (see here)

type ID = <T>(T) => T;
const identity: ID = x => x;

2: const identity: ID = x => x;
                             ^ Cannot assign function to `identity` because `T` [1] is incompatible with `T` [2] in the return value.
References:
1: type ID = <T>(T) => T;
                 ^ [1]
1: type ID = <T>(T) => T;
                       ^ [2]

However, I can make it work if I add generic type T to function definition (see here)

// @flow

type ID = <T>(T) => T;
const identity: ID = <T>(x) => x;

Can anyone explain what's going on here?

All 3 comments

Hmm, writing const identity = <T>(arg: T): T => arg works. I'm not sure why leaving off the explicit return type (you've got <T>(arg: T) => arg) breaks though.

Interestingly, flow suggest seems to break with the <T>(arg: T) => arg version; it just won't give me any suggestions.

Indeed, you should annotate return type explicitly.

I have a similar problem with this. In flow v0.75.0, the following patterns work and they all produce the same type signature: <T> (T) => T (see here)

// @flow

// function with implicit return type
function identity1<T>(x: T) {
  return x;
}

// function with explicit return type
function identity2<T>(x: T): T {
  return x;
}

// function expression with implicit return type
const identity3 = function<T>(x: T) {
  return x;
};

// function expression with explicit return type
const identity4 = function<T>(x: T): T {
  return x;
};

// arrow with implicit return type
const identity5 = <T>(x: T) => x;

// arrow with explicit return type
const identity6 = <T>(x: T): T => x;

console.log(identity1(123), identity1('123'));
console.log(identity2(123), identity2('123'));
console.log(identity3(123), identity3('123'));
console.log(identity4(123), identity4('123'));
console.log(identity5(123), identity5('123'));
console.log(identity6(123), identity6('123'));

But if I try to extract the type signature and use it as a standalone type for the function, it fails (see here)

type ID = <T>(T) => T;
const identity: ID = x => x;

2: const identity: ID = x => x;
                             ^ Cannot assign function to `identity` because `T` [1] is incompatible with `T` [2] in the return value.
References:
1: type ID = <T>(T) => T;
                 ^ [1]
1: type ID = <T>(T) => T;
                       ^ [2]

However, I can make it work if I add generic type T to function definition (see here)

// @flow

type ID = <T>(T) => T;
const identity: ID = <T>(x) => x;

Can anyone explain what's going on here?

Was this page helpful?
0 / 5 - 0 ratings