Conditional types in a stream

Is it possible to inject a variable into a stream based on a condition? Something like that:

const type = 'xyz';
const a: (type === 'xyz') ? number : string;

      

+3


source to share


2 answers


The short answer is no. The variable must be bound to a single type, which can include the type of the type union number | string

. Within a conditional block, Flow can infer a more specialized type. For example:

const a: number | string = "foo";
if(typeof a === "string"){
  a.split(); // OK!
} else {
  a.split(); // Error! a is a number
}

      



But note that these conditional branches are static and guarantee at compile time that the type will be inside each one.

+3


source


Typical conditions in a stream can be modeled using type calls $Call

:

type $If<X: boolean, Then, Else = empty> = $Call<
    & ((true, Then, Else) => Then)
    & ((false, Then, Else) => Else),
    X,
    Then,
    Else,
>;

type $Not<X: boolean> = $If<X, false, true>;
type $And<X: boolean, Y: boolean> = $If<X, Y, false>;
type $Or<X: boolean, Y: boolean> = $If<X, true, Y>;

type $Gte<X, Y> = $Call<
    & ($Subtype<X> => true)
    & (mixed => false),
    Y,
>;

// Usage example:

declare var a: $Gte<number, string>;

/* error  1 */ (a: true);
/* ok       */ (a: false);

declare var b: $Gte<number, number>;

/* ok       */ (b: true);
/* error  2 */ (b: false);

declare var c: $If<true, 1, 2>;

/* ok       */ (c: 1);
/* error  3 */ (c: 2);

declare var d: $If<false, 1, 2>;

/* error  4 */ (d: 1);
/* ok       */ (d: 2);

      



More usage examples can be found in the gist .

+3


source







All Articles