flow-runtime icon indicating copy to clipboard operation
flow-runtime copied to clipboard

Generics in function

Open ForbesLindesay opened this issue 8 years ago • 2 comments
trafficstars

This is a: Bug Report

Which concerns: babel-plugin-flow-runtime


What is the current behaviour?

function throwIfNull<T>(result: ?T): T {
  if (result === null || result === undefined) {
    throw error;
  }
  return result;
}

Outputs the following error:

ReferenceError: src/runner/validate-return-type.js: Reference to undeclared variable "T"
> 14 | function throwIfNull<T>(result: ?T): T {
     |                                      ^
  15 |   if (result === null || result === undefined) {
  16 |     throw error;
  17 |   }

What is the expected behaviour?

This should probably not really assert anything at runtime. I expect flow to use this, but probably not flow-runtime.


Which package versions are you using?

0.10.0

ForbesLindesay avatar Apr 16 '17 13:04 ForbesLindesay

The workaround I've found is to add:

// declare this so that flow-runtime ignores T
type T = mixed;

above the function. Flow will properly shadow this variable so it doesn't matter. flow-runtime will just use "mixed" when it can't recognise the type T.

ForbesLindesay avatar Apr 16 '17 13:04 ForbesLindesay

I've faced the similar issue, but can't reproduce it on clean create-react-app project.

Here the code

type Getter<Result> = (state: ServerDetailsState) => Result;

const localState = <T>(f: Getter<T>) => (state: State): T => f(state.serverDetails);

it generates two different versions in my app and create-react-app app

Here is create-react-app version

var localState = __WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.annotate(function localState(f) {
  var T = __WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.typeParameter('T');

  var _fType = __WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.ref(Getter, __WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.flowInto(T));

  __WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.param('f', _fType).assert(f);
  return __WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.annotate(function (state) {
    var _stateType = State;

    var _returnType = __WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.return(T);

    __WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.param('state', _stateType).assert(state);
    return _returnType.assert(f(state.serverDetails));
  }, __WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.function(__WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.param('state', State), __WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.return(T)));
}, __WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.function(function (_fn) {
  var T = _fn.typeParameter('T');

  return [__WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.param('f', __WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.ref(Getter, __WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.flowInto(T)))];
}));

and here is my app's version:

var localState = __WEBPACK_IMPORTED_MODULE_7_flow_runtime___default.a.annotate(function localState(f) {
  return __WEBPACK_IMPORTED_MODULE_7_flow_runtime___default.a.annotate(function (state) {
    return f(state.serverDetails);
  }, __WEBPACK_IMPORTED_MODULE_7_flow_runtime___default.a.function(__WEBPACK_IMPORTED_MODULE_7_flow_runtime___default.a.param("state", __WEBPACK_IMPORTED_MODULE_7_flow_runtime___default.a.ref(State)), __WEBPACK_IMPORTED_MODULE_7_flow_runtime___default.a.return(T)));
}, __WEBPACK_IMPORTED_MODULE_7_flow_runtime___default.a.function(function (_fn) {
  var T = _fn.typeParameter("T");

  return [__WEBPACK_IMPORTED_MODULE_7_flow_runtime___default.a.param("f", __WEBPACK_IMPORTED_MODULE_7_flow_runtime___default.a.ref(Getter, __WEBPACK_IMPORTED_MODULE_7_flow_runtime___default.a.flowInto(T)))];
}));

As you can see, second version lacks

  var T = __WEBPACK_IMPORTED_MODULE_3_flow_runtime___default.a.typeParameter('T');

definition and it crashes on a.return(T) line

Dema avatar Jun 22 '17 20:06 Dema