Skip to content

Instantly share code, notes, and snippets.

@kangax
Last active September 11, 2019 19:20
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save kangax/aa59598cf28d02f38579d8a95b5cbf92 to your computer and use it in GitHub Desktop.
Save kangax/aa59598cf28d02f38579d8a95b5cbf92 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
*/
/* 1. Accessing unknown properties on objects */
/* ------------------------------------------ */
// https://github.com/facebook/flow/issues/106
// https://flow.org/try/#0MYewdgzgLgBAhjAvDA3gXwNwCg4DoBmIIuARnAE4YwD01MAKgMoyAoBDAKbnkjkA0MAMQA2IAO6sYIANZA
// https://www.typescriptlang.org/play/#code/MYewdgzgLgBAhjAvDA3gXwNwCg4DoBmIIuARnAE4YwD01MAKgMoyAoBDAKbnkjkA0MAMQA2IAO6sYIANZA
const a = {};
a.foo.bar; // TS — error, Flow — ok
/* 2. Accessing unknown properties on functions */
/* -------------------------------------------- */
// https://flow.org/try/#0MYewdgzgLgBApjAvDAFASgFwwG4gJYAmSAfDAN4wC+AUHAHQBmIIQA
// https://www.typescriptlang.org/play/#code/MYewdgzgLgBApjAvDAFASgFwwG4gJYAmSAfDAN4wC+AUHAHQBmIIQA
const e = (): void => { }
e.foo // TS — error, Flow — ok
/* 3. Union refinement */
/* ------------------- */
// https://flow.org/try/#0C4TwDgpgBAYg9nKBeKBvKpIC4oHIBmCuUANFIXDgM7ABOAlgHYDmUAvgNwBQm0AQgENayNBnAQcuAEZDiZGbWp0mrTj3FQAsiAAqGlPEQAfKINrcuEAB5g4tYOQCujAMbB6cRhgg0AFMBxtPUgASjQuKCh6fCh-ADpeZCQUAiIw1AjIqBdPKjgAGwg4-LhmeIoQ7izs3IKikrLgOIVKzLYuNiA
// https://www.typescriptlang.org/play/#code/C4TwDgpgBAYg9nKBeKBvKpIC4oHIBmCuUANFIXDgM7ABOAlgHYDmUAvgNwBQm0AQgENayNBnAQcuAEZDiZGbWp0mrTj3FQAsiAAqGlPEQAfKINrcuEAB5g4tYOQCujAMbB6cRhgg0AFMBxtPUgASjQuKCh6fCh-ADpeZCQUAiIw1AjIqBdPKjgAGwg4-LhmeIoQ7izs3IKikrLgOIVKzLYuNiA
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
}
}
/* 4. Union refinement with typed return */
/* ------------------------------------- */
// https://github.com/facebook/flow/issues/4639
// https://flow.org/try/#0C4TwDgpgBAYg9nKBeKBvAPlAZggXFAZ2ACcBLAOwHMp0BfAbgChRIoAhAQ2OTUwCMu+ImSo0GjRlgCu5AMbBScclEoRg8OAHliAOSkAbfQAop+DTXZcAlPgD851IyhRiaqcWUsIcLFCkA6HEQkEKgAIhkAEwgsCghIsKhbKHIDfSh8KXooAHocqAAVAGUoQBQCKAhiYjhiABpYfTgAdzKKqpqnFzcPP0CEZFComLjIpJS0jL9svMKS8srquobm1oWO51dgd2UwoMSKPzHUw0ms3Pzi1falmEaW+evGWkYgA
// https://www.typescriptlang.org/play/#code/C4TwDgpgBAYg9nKBeKBvKAzBAuKBnYAJwEsA7AcygF8BuAKFEigCEBDQ5NKAI3dwJIVq9OhgCupAMbBicUlHIRg8OAHlCAOTEAbbQAoxuFVAA+LdgEpcAfmOo6UKISVjC8xhDgYoYgHRZEJCCoACIJABMIDDIIcJCoayhSHW0oXDEaKAB6LKgAFQBlKEAUAigIQkI4QgAaWG04AHcSsoqqhycXNx9-BGRgiKiY8ISklLSfTJz8otLyypq6xua5tsdnYFd5EID4sh8R5N1xjOzcwuXWhZh6ptnLuiogA
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
}
/* 5. Invocations with invalid types */
/* --------------------------------- */
// https://flow.org/try/#0KYDwDg9gTgLgBAMwK4DsDGMCWEVxsAZxgEYAKCAIwCsAuOAb0QgjqKkxQHM4BfASgYAoOHDQ4CEADbAAdJIidy1GQmZ8A3IJ6DB+ImRRJJkjXAD0ZuADF5AdziAUAjjAoUaABo4AFQDKj567QuoQkpKgAJsAIHMDhphbWdv4ublCevsmBUDqgkLCIqBjYuHowAEykhgC2dNUULgL0wqLiUrLyitUaWsFEFYbG8ZY2EPZOKR7efuNZveVhKJHRKLFDiaOZqenTAak54NDwyOhYOHghAMykfLVIVfVQQiJQwDBIUCjqIgkjY7uTGRme20QA
// https://www.typescriptlang.org/play/#code/KYDwDg9gTgLgBAMwK4DsDGMCWEVxsAZxgEYAKCAIwCsAuOAb0QgjqKkxQHM4BfASgYAoOHDQ4CEADbAAdJIidy1GQmZ8A3IJ6DB+ImRRJJkjXAD0ZuADF5AdziAUAjjAoUaABo4AFQDKj567QuoQkpKgAJsAIHMDhphbWdv4ublCevsmBUDqgkLCIqBjYuHowAEykhgC2dNUULgL0wqLiUrLyitUaWsFEFYbG8ZY2EPZOKR7efuNZveVhKJHRKLFDiaOZqenTAak54NDwyOhYOHghAMykfLVIVfVQQiJQwDBIUCjqIgkjY7uTGRmex4QA
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
}
/* 6. "enums" validity */
/* ------------------- */
// https://flow.org/try/#0C4TwDgpgBAIglgJwgY2HA9gOygXigRigB8oAmAbgCgIAPMdBYKAMwFdNUNtgIBnYABQA3AFyxEKNFgCUUAN5QAvpR78B+AAwbp5KAHo9UAGIAbdAHcogFAIoEBAgYAaKABUAytdv2GlIA
// https://www.typescriptlang.org/play/#code/C4TwDgpgBAIglgJwgY2HA9gOygXigRigB8oAmAbgCgIAPMdBYKAMwFdNUNtgIBnYABQA3AFyxEKNFgCUUAN5QAvpR78B+AAwbp5KAHo9UAGIAbdAHcogFAIoEBAgYAaKABUAytdv2GQA
type Direction = 1 | 2;
export function test(v: Direction) { }
test(100); // Flow — error, TS — error
/* 7. "enums" validity with typeof */
/* ------------------------------- */
// https://flow.org/try/#0MYewdgzgLgBAHjAvDAjAbgFCkrAnkmAJkylwAcBTGAEQEsAnC4KW8A0ykAM3hgB8YHCtxi5MFOGRD1YXAK5hmrMIIrQAFADcAXDQZMW4AJQwA3jAC+GKGqjqUABgdG0MAPRuYAMQA2IAO4wgCgEMGAgMBT09NIANDAAKgDKwRFR0kA
// https://www.typescriptlang.org/play/#code/MYewdgzgLgBAHjAvDAjAbgFCkrAnkmAJkylwAcBTGAEQEsAnC4KW8A0ykAM3hgB8YHCtxi5MFOGRD1YXAK5hmrMIIrQAFADcAXDQZMW4AJQwA3jAC+GKGqjqUABgdG0MAPRuYAMQA2IAO4wgCgEMGAgMBT09NIANDAAKgDKwRFR0kA
const x = 1;
const y = 2;
type Direction = typeof x | typeof y;
export function test(v: Direction) { }
test(100); // Flow — no error, TS — error
/* 8. Dynamic refinement */
/* --------------------- */
// https://flow.org/try/#0C4TwDgpgBAglC8UDeUCGAuKBnYAnAlgHYDmUAPlIQK4C2ARhLlAL4DcAUKJFAEILJpMOAiRYd2EAB5gA9rmBQAZlUIBjYPhmEowCDgAUGWAEpk7KGgB0qfgBYOzdu1VacUOpj6IURgOSKZGV8xTj1gfTpjVigAehioADEAGxkAdyhAFAIoRlw5ABooABUAZUyoGQBrdjprS2AZABk0xgBhVCwIfSigA
// https://www.typescriptlang.org/play/#code/C4TwDgpgBAglC8UDeUCGAuKBnYAnAlgHYDmUAPlIQK4C2ARhLlAL4DcAUKJFAEILJpMOAiRYd2EAB5gA9rmBQAZlUIBjYPhmEowCDgAUGWAEpk7KGgB0qfgBYOzdu1VacUOpj6IURgOSKZGV8xTj1gfTpjVigAehioADEAGxkAdyhAFAIoRlw5ABooABUAZUyoGQBrdjprS2AZABk0xgBhVCwIfSigA
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();
/* 9. Dynamic refinement #2 */
/* ------------------------ */
// https://flow.org/try/#0GYVwdgxgLglg9mABABwE4zFAFADwFyJggC2ARgKaqIA+iAzlOmAOYCUiA3gFCKIQJ04AG3IA6IXGa5WAbi4BfLl3I5kcVFEShIsBIijkGWYHDikAhqgKlTI82HbdeIzTkQBeRAEYADD7m8APSBiG4wdIj2iHDI5EhQAJ6xADT0cIgJcCB8USrI9gAmiDBQPIjBocURRGSUiAAWlORlMMCIxqYWqI5lQSFhEQxMzA1NvZWeAOQAkmAAbuZCMAWTMuUhAGISAO6IgCgE0QDWqQAqAMr7iJSo6mWKZRUDhCQUVLRDGCONqM28aBjYHCydaEdLXW7yIA
// https://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABABwE4zFAFADwFyJggC2ARgKaqIA+iAzlOmAOYCUiA3gFCKIQJ04AG3IA6IXGa5WAbi4BfLl3I5kcVFEShIsBIijkGWYHDikAhqgKlTI82HbdeIzTkQBeRAEYADD7m8APSBiG4wdIj2iHDI5EhQAJ6xADT0cIgJcCB8USrI9gAmiDBQPIjBocURRGSUiAAWlORlMMCIxqYWqI5lQSFhEQxMzA1NvZWeAOQAkmAAbuZCMAWTMuUhAGISAO6IgCgE0QDWqQAqAMr7iJSo6mWKZRUDhCQUVLRDGCONqM28aBjYHCydaEdLXW7yIA
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
}
/* 10. Classes */
/* ----------- */
// https://flow.org/try/#0MYGwhgzhAECCB2BLAtmE0DeBfAUKSMAwmAC7QCmAHiefACYwIpqY7TTLkD2A7gBQBKTLlz4o0ACJcA5sJw4qABy4AnMgDMArvGAlEXeNBoQSfMElQgIALjgW0AbQC6QjG2jnmVgHSLNEAAs+eHIeSRlBAQBuaAB6WOh1EF5oQBQCChUVVQAaaAAVAGU06HguDKyVHFw8AxNoYFIbaGISZ2gAXmhnKPljUwaSCGi4hKSU9PJMnPyi9NLy1XkBiG91VQBRMGAggY6APnrSb05eSKigA
// https://www.typescriptlang.org/play/#code/MYGwhgzhAECCB2BLAtmE0DeBfAUKSMAwmAC7QCmAHiefACYwIpqY7TTLkD2A7gBQBKTLlz4o0ACJcA5sJw4qABy4AnMgDMArvGAlEXeNBoQSfMElQgIALjgW0AbQC6QjG2jnmVgHSLNEAAs+eHIeSRlBAQBuaAB6WOh1EF5oQBQCChUVVQAaaAAVAGU06HguDKyVHFw8AxNoYFIbaGISZ2gAXmhnKPljUwaSCGi4hKSU9PJMnPyi9NLy1XkBiG91VQBRMGAggY6APnrSb05eSKigA
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());
/* 11. Computed key as generic */
/* --------------------------- */
// https://flow.org/try/#0CYUwxgNghgTiAEAzArgOzAFwJYHtVJxwB4AVALngGcMYtUBzAPgAoBbATwFFVlWKSANPAAOUDBhAxUFAN4BtANYh2-ALoVqtBgF8AlPwDcAKDB5q8AB7wAvARzMA5ACNYDoTPguYFBw-h6DeAB6IPgAMQgcAHd4QBQCeFQceEkYHBgTMwx4dhs7R0RCN3gPLx8-AODQiOi4hKSUtKMgA
// https://www.typescriptlang.org/play/#code/CYUwxgNghgTiAEAzArgOzAFwJYHtVJxwB4AVeEADwxFWAGd46MYtUBzAPgAoBbATwCiqZDwBc8EgBp4ABygZqMVOIDeAbQDWIPvFYSAuuKYt2AXwCU4kgG4AUGDxN4FeAF4COLgHIARrC-SKvB+MOJeXvAW1vAA9DESAMrwgCgE8Kg45DAwODD2jhjwOu6IhN4lOAHwQSFhEVGx8SRJqSBZOUA
// 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
/* 12. Refining boolean checks */
/* --------------------------- */
// https://flow.org/try/#0GYVwdgxgLglg9mABMMAKAHgLkQQzATwEpsAjOOAGwFM9EBSCACyogGsBnRAbwChFEATlSggBSKPgAOVOMETpEAXmWIA5OygCYYAOaqA3DwC+PCAg3IYFKFSEATJYgDaq4OVUAaRAFYvmkFQAugB0wFY2AqgohIZh1rZUdk4ADCFQcAAycADutgDCOOxUqDGIAPRliLYCcAJAA
// https://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABMMAKAHgLkQQzATwEpt1EYBnRcqAJxjAHNEBvAKEURoFMoQako+AA5c4wRKQC80xAHJqdRrIDcrAL6sICashgAbKF24ATRJMQBtWcDhxZAGkQBWR7RBcAugDpg+wzVQUQlVfAyMuYwsABm8oOAAZOAB3IwBhHHIuVGDEAHpcxDA4RCMaOBogA
// TS
function fn(x: any): x is string {
return typeof x === 'string';
}
const filtered = ['foo', 5, true].filter(fn);
filtered[0].toLowerCase(); // no error
// Flow
function fn(x: any): boolean %checks {
return typeof x === 'string';
}
const filtered = ['foo', 5, true].filter(fn);
filtered[0].toLowerCase(); // error
/* 13. Type coercion on a generic Object */
/* ------------------------------------- */
// https://flow.org/try/#0GYVwdgxgLglg9mABMAFASgFyIPICMBWAptIgN4BQiiAToVCNUqQL7mvmpqIDUiAjIgD0gxABUAyokAoBIkLVqcagBpEAMQA2cAO7TEYOLPmKgA
// https://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABMAFASgFyIPICMBWAptIgN4BQiiAToVCNUqQL7mvmpqIDUiAjIgD0gxABUAyokAoBIkLVqcagBpEAMQA2cAO7TEYOLPmKgA
function f(): Object {
return {}
}
f() + 1 // TS — error, Flow — no error
/* 14. Readonly property operator assignment */
/* ----------------------------------------- */
// https://github.com/facebook/flow/issues/7195
// https://flow.org/try/#0MYewdgzgLgBAZiEAuGBvA1AIwIYCcVgCuAtpgKa4C+MAvGjvjAIyUBQrCIAdAzOnUxgB6ITABiAGxAB3GAFoYYEDAq4QuVkA
// https://www.typescriptlang.org/play/#code/MYewdgzgLgBAZiEAuGBvATgUwIYBNwA2AnjAEbbopgCuAtqZugL4wC8a5lMAjEwFB8EIAHScYAanbcYAehkwAKgGUYAWhiN0IdHyA
// 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
/* 15. Indexer prevents property lookup on classes and interfaces */
/* -------------------------------------------------------------- */
// https://github.com/facebook/flow/issues/4014
// https://flow.org/try/#0CYUwxgNghgTiAEkoGdnwBrwN4Ch7wDMB7IgLnmQBcYBLAOwHMBuPeAbQGsQBPcugVwC2AIxAwAunyGiYLAL4scoJHHgA3WPAAe5dIq1sA5MSKHxTeAHpL8AGIQiAd3gBaeGJhEYAGngAVAGVXeDoidxhPGBwgA
// https://www.typescriptlang.org/play/#code/CYUwxgNghgTiAEkoGdnwBrwN4Ch7wDMB7IgLnmQBcYBLAOwHMBuPeAbQGsQBPcugVwC2AIxAwAunyGiYLAL4scoJHHgA3WPAAe5dIq1sA5MSKHxTeAHpL8AGIQiAd3gBaeGJhEYAGngAVAGVXeDoidxhPGBwgA
declare class X {
foo: string;
[key: number]: number;
};
declare var x: X;
x['foo']; // Flow - error, TS - no error
/* 16. Mixed indexers */
/* ------------------ */
// https://news.ycombinator.com/item?id=16780836
// https://flow.org/try/#0C4TwDgpgBAKlC8UDeUD0qoDEA2B7A7lALRQB2uUEATlblQDSwDKxlNdAUFFAB4BcZAK4BbAEbUA3FygBtAM4C5wKgEtSAcwC6A0blzYIAQ1JSAvlIDGuUkqjCBcRCn5QAjIx4AvAcsHRzHMIyAORewQB0coKiSlQAFAAMjK4AlJoIUL4QUsLhPOHAuJgqPBAAJnEpEmgYAMJUhnIAFhByQA
// https://www.typescriptlang.org/play/#code/C4TwDgpgBAKlC8UDeUD0qoDEA2B7A7lALRQB2uUEATlblQDSwDKxlNdAUFFAB4BcZAK4BbAEbUA3FygBtAM4C5wKgEtSAcwC6A0blzYIAQ1JSAvlIDGuUkqjCBcRCn5QAjIx4AvAcsHRzHMIyAORewQB0coKiSlQAFAAMjK4AlJoIUL4QUsLhPOHAuJgqPBAAJnEpEmgYAMJUhnIAFhByQA
type T = { // Flow - no error, TS - error
x: number;
[s: string]: boolean;
};
const m: T = { x: 1, xz: true };
m['xz'.substr(0, 1)] = true;
m.x.toFixed(); // Crashes
/* 17. "Exact" object extension */
/* ---------------------------- */
// https://flow.org/try/#0C4TwDgpgBAqgzhATlAvFA3gHwFBSgVwUQDsBDAWwgC4o5hEBLYgcwBpcoJzSGAbGuoxbZMAX2zYAxgHtidKNIBGAKwCMNeElQYOAOn3oCRMpRoByAB5moo1lD0HO3PuZDXbD3YcWkAXq-c7AHogqAAxXmkAdyhAFAJORERpRGxxPClZeSVlACYNIm0AeRUISWBdUjg4BmZiAApDQiQTaihLMzsuHn42qztbDCdugLsAM2lpcx9EdwBKKBDwyJj4pCSUjLlgKDAksG06+ZQAPjamkgoIMwBubGzVAG1d6TBDgF1tduuF0IjouIUAGsgA
// https://www.typescriptlang.org/play/#code/C4TwDgpgBAqgzhATlAvFA3gKClArgxAOwEMBbCALijmEQEtCBzAGmyglOLoBsqb6mmAL6ZMAYwD2hGlAkAjAFYBGKvCSoMbAHQ70eAiXJUA5AA9jUIcyjbd7TjxMgLV21r1ziALycvrAen8oABUAZShAFAIoQgl2REQJRGE2cSkZeQUAJlUCDQB5RQgxYC1iODg6RkIACj18JENKKDNjaw4uXmbzaysMew7fawAzCQkTT0QXAEooQJDwqJi4hKTU6WAoMASwDWqZlAA+ZvqiMghjAG5MDKUAbS2JMD2AXQ0Wi9mgsMjo2KQVoA
// Flow
type User = {|
username: string,
email: string
|}
const obj1: User = {
...{ username: 'x' },
...{ email: 'y' },
...{ baz: 'y' }, // Flow — error
}
const obj2: User = Object.assign({ username: 'x', email: 'x', }, { email: 'y', foo: 'bar' }) // Flow — error
const prop = () => 'username';
obj1[prop()] = 'x'; // Flow — ok
// TS
type User = {
username: string,
email: string
}
const obj1: User = {
...{ username: 'x' },
...{ email: 'y' },
...{ baz: 'y' }, // TS — no error
}
const obj2: User = Object.assign({ username: 'x', email: 'x', }, { email: 'y', foo: 'bar' }) // TS — no error
const prop = () => 'username';
obj1[prop()] = 'x'; // TS — no error
/* 18. Destructuring */
/* ----------------- */
// https://flow.org/try/#0MYewdgzgLgBA2gdwDQwIYqgXRgXhgbwAcAuGAcjIF8BuGAejpgDEAbEBGQFAIYwQYBTAE6CQglABUAylwHDRQA
// https://www.typescriptlang.org/play/#code/MYewdgzgLgBA2gdwDQwIYqgXRgXhgbwAcAuGAcjIF8BuGAejpgDEAbEBGQFAIYwQYBTAE6CQglABUAylwHDRQA
const [w, a, t] = {p: ''}; // Flow — no error, TS — error
/* 19. Spreading w. different types */
/* -------------------------------- */
// https://flow.org/try/#0MYewdgzgLgBAHjAvDA2gcjmgugbgFCiSwCeSqAjLgeNDAF5koB0LcANDC08VXnSgAYsTKCAAyIAO4BTAE4BhAIYRpACgCUOGAHptMACoBlGIBQCGHNkhZHAGIAbKaZhgQ52Zdl8UlEeKlylFQ0tXQNjMwsrWwdJJ0jZIA
// https://www.typescriptlang.org/play/#code/MYewdgzgLgBAHjAvDA2gcjmgugbgFCiSwCeSqAjLgeNDAF5koB0LcANDC08VXnSgAYsTKCAAyIAO4BTAE4BhAIYRpACgCUOGAHptMACoBlGIBQCGHNkhZHAGIAbKaZhgQ52Zdl8UlEeKlylFQ0tXQNjMwsrWwdJJ0jZIA
const x = ['x'];
const y = [1];
const z = [...x, ...y];
z[0].toLowerCase(); // TS — error, Flow — no error
z[1].toLowerCase(); // TS — error, Flow — error
/* 20. apply + bind */
/* ---------------- */
// https://flow.org/try/#0GYVwdgxgLglg9mABMMAKAlIg3ogvgKBQDoBDABzIBsBPIgIxjABNUV0g
// https://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABMMAKAlIg3ogvgKBQDoBDABzIBsBPIgIxjABNUV0g
function fn() { }
fn.apply.bind(fn) // Flow — error, TS — no error
@kangax
Copy link
Author

kangax commented Jun 24, 2019

@ssidorchik agreed, updated the gist

@goodmind
Copy link

goodmind commented Jun 24, 2019

/* Readonly property operator assignment */
/* ------------------------------------- */
// https://github.com/facebook/flow/issues/7195

// 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
/* Indexer prevents property lookup on classes and interfaces */
/* ----------------------------------------------------------- */
// https://github.com/facebook/flow/issues/4014
declare class X {
  foo: string;
  [key: number]: number;
};

declare var x: X;

x['foo']; // Flow - error, TS - no error

@goodmind
Copy link

/* Mixed indexers */
/* --------------- */
// https://news.ycombinator.com/item?id=16780836
type T = { // Flow - no error, TS - error
  x: number;
  [s: string]: boolean;
};
const m: T = { x: 1, xz: true };
m['xz'.substr(0, 1)] = true;
m.x.toFixed(); // Crashes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment