Last active
September 11, 2019 19:20
-
-
Save kangax/aa59598cf28d02f38579d8a95b5cbf92 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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 |
@ssidorchik agreed, updated the gist
/* 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
/* 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
With
strictNullChecks
andnoImplicitReturns
TypeScript catches errors in "invocations with types other than annotations" section.https://typescript-play.js.org/#code/PTAEEsDsDcHsGMCGAXctIGdQHdzIBajICeADgKZawHkBOR+ikoTk1KamAUF+QB6lYtZKABmAV0jxU6IpWQBGABSwARgCsAXKADeY2LG0ZktKAHNQAXwCUurqFDx0GWABtyAOlewzKjR9EDawBuLkseZHllSHFXVxDQEFAAMW9sUEAUAlA6WiEAGlAAFQBlTNBYAGsuSONlSQATclEocnqEpNTYdKyc-KLSrMqefkFhMUlpTjljACYlGIBbbUXVOlsde0dnN09vX0WQsOr5OZi49rBO7uzaXNoCkrKhmuQ5hqaWtuDEy7Sy3vu-SeVV4AiEIgkUhkzBeAGYlNZluIFqt6BsHLRyMhxLRIN8fik-j1bn1HoMqpYgA
Considering that these options are recommended defaults, I'd say that it's on the same level with Flow.