codemix / babel-plugin-typecheck

Static and runtime type checking for JavaScript in the form of a Babel plugin.
MIT License
886 stars 44 forks source link

Typecheck within a case statement causes reference error #123

Closed prewk closed 7 years ago

prewk commented 8 years ago

Am I correct in assuming that this should work?

// a.js

export type Foo = { id: number; title: string; type: 'FOO' | 'BAR'; };

// b.js

import type { Foo } from './a';

const item = { id: 123, title: 'Lorem ipsum', type: 'FOO' };
const x: Foo = item;

I have a similar situation where it keeps saying TypeError: Value of variable "item" violates contract. Expected: Foo Got: { id: number; title: string; type: string; }

However, it works if I keep everything in one file:

type Foo = { id: number; title: string; type: 'FOO' | 'BAR'; };

const item = { id: 123, title: 'Lorem ipsum', 'FOO' };
const x: Foo = item;

In the first, not working, example I've experimented with trying this out:

const item = { id: 123, title: 'Lorem ipsum', 'FOO' };
console.log(Foo(item)); // Logs 'true'
const x: Foo = item;

Which makes me even more confused, because if it's failing, it should return false, right?

Thanks for an awesome lib!

phpnode commented 8 years ago

@prewk please could you paste your babelrc?

prewk commented 8 years ago

Sure:

{
  "presets": ["es2015", "react", "stage-0"],
  "plugins": ["transform-runtime", ["typecheck", {
    "disable": {
      "production": true
    }
  }]]
}

My project's a closed-source monolith, so it's hard for me to reproduce the exact circumstances. I'm first and foremost looking for direction on whether my assumption is correct or not about the export/import usage.

phpnode commented 8 years ago

@prewk this is happening because of babel6's plugin munging behaviour which causes all sorts of incompatibilities between plugins.

The solution is to set passPerPreset: true in your babelrc. If this doesn't work, try swapping the order of your es2015, react and stage-0 presets. Closing the issue but will reopen if it's still broken,

prewk commented 8 years ago

I upgraded from babel 6.3 to 6.5 to be able to use passPerPreset, got this error which I solved by using this .babelrc:

{
  "passPerPreset": true,
  "presets": ["react", "stage-0", "es2015-loose"],
  "plugins": ["transform-runtime", ["typecheck", {
    "disable": {
      "production": true
    }
  }]]
}

My problem is now resolved, thank you!

phpnode commented 8 years ago

@prewk glad to hear it's working.

prewk commented 8 years ago

Encountered a weird bug I suppose origins in Babel?

Consider this:

import type { Service } from './types';

function reduce(state, action) {
  switch (action.type) {
    case SET_SERVICES:
      const services:Array<Service> = action.services;

      console.log(services); // ERROR: services is undefined

      return state;
    default:
      return state;
  }
}

..but, with block scoping around the case:

import type { Service } from './types';

function reduce(state, action) {
  switch (action.type) {
    case SET_SERVICES: {
      const services:Array<Service> = action.services;

      console.log(services); // SUCCESS: services is as it should be

      return state;
    }
    default:
      return state;
  }
}
phpnode commented 8 years ago

@prewk do you get the same when you disable typecheck?

prewk commented 8 years ago

Actually no, so this might be an actual bug.

Radivarig commented 8 years ago

I get the error when using const or let but not with var.

phpnode commented 7 years ago

@Radivarig this works in flow-runtime.