Skip to content

More flow improvements #564

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 20, 2016
Merged

More flow improvements #564

merged 1 commit into from
Jul 20, 2016

Conversation

amadeus
Copy link
Collaborator

@amadeus amadeus commented Jul 20, 2016

  • Fixed a couple funky ? (maybe) cases
  • Improved argument definitions
  • Misc tweaks

These fixes are in regards to this comment

The updated file that should be validly matched, is:

let array: number[] = [1, 2, 3.14, 42];
let theAnswer: number = array[3]; // 42
let offTheEnd: number = array[100]; // No error
let array2: Array<string> = ["an alternate", "syntax", "for arrays"];
let tuple: [string, number, boolean] = ["foo", 0, true];

// Indexing into the array will return the type at a given index.
(tuple[0]: string);
(tuple[1]: string);

// Indexing into an statically unknown index will return a general type.
declare var unknownNumber: number;
// `void` is none of `string`, `number`, or `boolean`
(tuple[unknownNumber]: void);
(tuple[unknownNumber]: string|number|boolean); // OK

// Values written must be compatible with the type at that index.
tuple[1] = -1;
tuple[0] = false;

let object: {foo: string, bar: number} = {foo: "foo", bar: 0};
(object.foo: string);

function durp(): { durp: { what: {} } } {
}

function durp(): [number] {
}

function durp2(): number {
}

function durp3(): <MyClass> {
}

function durp3(): Class<MyClass> {
}


// Property writes must be compatible with the declared type.
object.bar = "bar";

let coolRating: {[id:string]: number} = {};
coolRating["sam"] = 10; // Yes, it's a 0-10 scale.

function makeCallable(): { (x: number): string; foo: number } {
  function callable(number) {
    return number.toFixed(2);
  }
  callable.foo = 123;
  return callable;
}

var callable = makeCallable();

var callableReturn: string = callable(Math.PI); // "3.14"
var callableFoo: number = callable.foo; // 123

var anyObject: Object = {};
anyObject.foo.bar.baz; // OK

function greatestCommonDivisor(a: number, b: number): number {
  if (!b) {
    return a;
  }

  return greatestCommonDivisor(b, a % b);
}

async function getFriendNames(
  friendIDs: Promise<number[]>,
  getFriendName: (id: number) => Promise<string>,
): Promise<string[]> {
  var ids = await friendIDs;
  var names = await Promise.all(ids.map(getFriendName));
  return names;
}

function *infinity(): Generator<number,void,void> {
  var n = 0;
  while (true) {
    yield n++;
  }
}

var anyFunction: Function = () => {};
anyFunction("foo", "bar").baz.quux; // OK

class MyClass {
  foo: string;
  constructor(foo: string) {
    this.foo = foo;
  }
  bar(): string {
    return this.foo;
  }
}

var myInstance: MyClass = new MyClass("foo");
(myInstance.foo: string);
(myInstance.bar(): string);

interface Fooable {
  foo(): string;
}

class AFoo {
  foo() { return "foo from A" };
}

class BFoo {
  foo() { return "foo from B" };
}

(new AFoo: Fooable);
(new BFoo: Fooable);

function DietClass(foo: string) {
  this.foo = foo;
}

DietClass.prototype.bar = function() {
  return this.foo;
}

var myDietInstance: DietClass = new DietClass("foo");
(myDietInstance.foo: string);
(myDietInstance.bar(): string);

var myClass: Class<MyClass> = MyClass;
var myInstance2 = new myClass("foo");

type ObjectWithManyProperties = {
  foo: string,
  bar: number,
  baz: boolean,
  qux: (foo: string, bar: number) => boolean;
}

type GenericObject<T> = { foo: T };

var numberObject: GenericObject<number> = { foo: 0 };
var stringObject: GenericObject<string> = { foo: "foo" };

class GenericClass<T> {
  x: T;
  durp: {
    what: who
  }
  constructor(x: T) {
    this.x = x;
  }
}

var o: ?string = null;
if (o == null) {
  o = 'hello';
}
print(o.length);


class Durp {}

var numberInstance: GenericClass<number> = new GenericClass(0);
var stringInstance: GenericClass<string> = new GenericClass("");

function findMax<T> (arr: T[], compare: (a: T, b: T) => number) {
  var sorted = arr.sort(compare);
  return sorted[sorted.length - 1];
}

// Annotations included for example purposes only.

[1, 2, 3].map((num: number): number => num * 2)


declare type ClassValue = string | {[key: string]: any};

declare module 'classnames' {
  declare function exports(...classes: Array<?ClassValue>): string;
}

declare type ClassValue = string | {[key: string]: any};

declare module 'classnames' {
  declare function exports(...classes: Array<?ClassValue>): string;
}

// You can mixin more than one class
declare class MyClass extends Child mixins MixinA, MixinB {}
declare class MixinA {
  a: number;
  b: number;
}
// Mixing in MixinB will NOT mix in MixinBase
declare class MixinB extends MixinBase {}
declare class MixinBase {
  c: number;
}
declare class Child extends Base {
  a: string;
  c: string;
}
declare class Base {
  b: string;
}

var c = new MyClass();
(c.a: number); // Both Child and MixinA provide `a`, so MixinA wins
(c.b: number); // The same principle holds for `b`, which Child inherits
(c.c: string); // mixins does not copy inherited properties,
               // so `c` comes from Child

declare module 'deep-equal' {
  declare type Options = {
    strict: false
  };

  declare function exports (a: any, b: any, opts: ?Options): boolean;
}

declare var __IOS__: bool;
declare var __ANDROID__: bool;
declare var __MOBILE__: bool;
declare var __WEB__: bool;

declare var process: {
  env: {
    API_ENDPOINT: string,
    API_VERSION: number,
    CDN_HOST: ?string,
    NODE_ENV: 'production' | 'development',
    LOCATION: 'history' | 'hash'
  }
};

declare function requestAnimationFrame(callback: (timestamp: ?number) => void): number;
declare function cancelAnimationFrame(requestID: number): void;

// TODO: these should go somewhere else

declare type Emoji = {
  id: string,
  name: string
};

declare type Source = {
  uri: ?string
};

declare type Application = {
  id: string,
  name: string,
  icon: ?string
}

declare type ConnectionRecord = {
  name: string,
  type: string
}

declare type Style = {[key: string]: string | number}

declare module 'StylusModule' {
}

declare module 'platform' {
  declare class OS {
    architecture: ?string;
    family: ?string;
    version: ?string;
    toString: () => string;
  }

  declare class Platform {
    description: ?string;
    layout: ?string;
    manufacturer: ?string;
    name: ?string;
    prerelease: ?string;
    product: ?string;
    ua: ?string;
    version: ?string;

    os: OS;

    parse: (ua: Object | string) => Platform;
    toString: () => string;
  }

  declare var exports: Platform;

}
declare module Misc {
  declare var DEBUG: bool;
  declare function isLeapYear(year: string): bool;
  declare class Counter {
    val: number;
    incr(): void;
  }
  declare type Response = 'yes' | 'no' | 'maybe';
  declare interface Stack<T> {
    push(item: T): void;
    pop(): T;
    isEmpty(): bool;
  }
}
declare class List<T> {
  map<U>(f: (x: T) => U): List<U>;
}

declare function foo(n: number): string;

function fooList(ns: List<number>): List<string> {
  return ns.map(foo);
}

declare export var className: string;

type Matrix = number[][]; // type of input and output for our function

type Result = Done | Error; // a disjoint union type with two cases
type Done = { status: 'done', answer: Matrix };
type Error = { status: 'error', message: string };

class Foo { }
class Bar { }
// b ends up being a Foo type, since f evaluates to Foo
var b: { f : typeof Foo } = { f : Foo };
// Since the type of b.f is typeof Foo (i.e. Class<Foo>), the following
// assignment is valid because the type of the new instance is Foo:
var inst1: Foo = new b.f();
// However, this fails because the type of the new instance is not Bar:
var inst2: Bar = new b.f();

declare module 'react-native' {
  declare interface IAsyncStorage {
    getItem(
      key: string,

      callback?: ?(error: ?Error, result: ?string) => void
    ): Promise;

    setItem(
      key: string,
      value: string,
      callback?: ?(error: ?Error) => void
    ): Promise;

    removeItem(
      key: string,
      callback?: ?(error: ?Error) => void
    ): Promise;

    clear(
      callback?: ?(error: ?Error) => void
    ): Promise;

    getAllKeys(
      callback?: ?(error: ?Error, keys: ?Array<string>) => void
    ): Promise;

    multiGet(
      keys: Array<string>,
      callback?: ?(errors: ?Array<Error>, result: ?Array<Array<string>>) => void
    ): Promise;
  }

  declare var AsyncStorage: IAsyncStorage;
}

class Box<T> {
  _value: T;

  constructor(value: T) {
    this._value = value;
  }
}

type Authenticator = (str: string) => Promise<?boolean> | ?boolean;

type Accessor<T, V> = (activityItem: T) => ?V;

function innerFunctionReturnTypes() {
  return ['a','b','c','d'].map((letter: string, index: number): boolean => {
    return index % 2 === 0;
  });
}

* Fixed a couple funky maybe cases
* Improved argument definitions
* Misc tweaks
@amadeus amadeus mentioned this pull request Jul 20, 2016
@amadeus amadeus merged commit c7dca1b into develop Jul 20, 2016
@amadeus amadeus deleted the even-more-flow-fixes branch July 20, 2016 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant