Skip to content

Instantly share code, notes, and snippets.

@goodmind
Forked from kangax/flow_ts_tests.js
Last active June 24, 2019 23:26
Show Gist options
  • Save goodmind/3020f43331c9c845b5f417d77e29c4c3 to your computer and use it in GitHub Desktop.
Save goodmind/3020f43331c9c845b5f417d77e29c4c3 to your computer and use it in GitHub Desktop.
/*
A collection of tests where Flow and TypeScript might have different behavior
Some tests are borrowed from https://github.com/vkurchatkin/typescript-vs-flow
Some tests now have the same behavior as the new versions of Flow/TS have fixed the bugs and improved type safety
*/
/* Accessing unknown properties on objects */
/* --------------------------------------- */
// https://github.com/facebook/flow/issues/106
const a = {};
a.foo.bar; // TS — error, Flow — ok
/* Accessing unknown properties on functions */
/* ----------------------------------------- */
const e = (): void => { }
e.foo // TS — error, Flow — ok
/* Union refinement */
/* ---------------- */
type Foo = { type: 'foo' , foo: string };
type Bar = { type: 'bar' , bar: string };
type MyType = Foo | Bar;
export function test(t: MyType) {
if (t.type === 'foo') {
console.log(t.foo); // Flow — no error, TS — no error
console.log(t.bar) // Flow — error, TS — error
}
}
/* Union refinement with typed return */
/* ---------------------------------- */
// https://github.com/facebook/flow/issues/4639
type Foo = {| foo: string |};
type Bar = {| bar: string |};
function getFooOrNull(u: Foo | Bar): ?Foo {
return typeof u.foo === "undefined" ? null : u; // TS — error, Flow — error
return u.foo === undefined ? null : u; // TS — error, Flow — error
return "foo" in u ? null : u; // TS — error, Flow — error
}
/* Invocations with invalid types */
/* ------------------------------ */
export function test1(obj: { foo: string }) {
console.log(obj.foo);
}
test1(null); // Flow — error, TS — error
test1(undefined); // Flow — error, TS — error
export function test2(num: number) {
console.log(num);
}
test2(null); // Flow — error, TS — error
test2(undefined); // Flow — error, TS — error
export function test3(): number {
return; // Flow — error, TS — error
}
/* "enums" validity */
/* ---------------- */
type Direction = 1 | 2;
export function test(v: Direction) { }
test(100); // Flow — error, TS — error
/* "enums" validity with typeof */
/* ---------------------------- */
const x = 1;
const y = 2;
type Direction = typeof x | typeof y;
export function test(v: Direction) { }
test(100); // Flow — no error, TS — error
/* Dynamic refinement */
/* ------------------ */
type A = { a: string | number };
type B = { a: string };
export function test(a: A) {
a.a = 4;
}
const b: B = { a: 'foo' };
test(b); // Flow — error, TS — ok
b.a.toLowerCase();
/* Dynamic refinement #2 */
/* --------------------- */
function print(x: number | string) {
console.log(x);
}
export function test(foobar: boolean) {
let x = 100;
// x is an open type, so you can expand it
// x is number here
if (foobar) {
// x is string here
x = 'Invalid'; // Flow — ok, TS — error
}
// x is number | string here
print(x); // no error
}
/* Classes */
/* ------- */
class Animal {}
class Cat extends Animal {
meow() {}
}
class Dog {}
export function test(animals: Animal[]) {
animals.push(new Dog()); // flow — error, TS — no error
}
const cats: Cat[] = [];
test(cats); // flow — error, TS — no error
cats.forEach(cat => cat.meow());
/* Computed key as generic */
/* ----------------------- */
// TS
declare function foo<T extends string>(myEnum: T, pattern: {[key in T]: string}): T;
const x = foo('bar', { bar: '' }); // TS — no error
const y = foo('foo', { bar: '' }); // TS — error
// Flow
declare function foo<T: string>(myEnum: T, pattern: {[key: T]: string}): T;
const x = foo('bar', { bar: '' }); // Flow — no error
const y = foo('foo', { bar: '' }); // Flow — no error
/* Readonly property operator assignment */
/* ------------------------------------- */
// TS
const foo: {readonly bar: number} = {bar: 1}
foo.bar += 1 // TS - error
// Flow
const foo: {+bar: number} = {bar: 1}
foo.bar += 1 // Flow - no error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment