From 06bc7c9be5fecd6958fb986a0724f63cb59f9bde Mon Sep 17 00:00:00 2001 From: Aldwin Vlasblom Date: Fri, 8 Jan 2021 14:45:43 +0100 Subject: [PATCH] Add branch awareness and tests for the type of 'alt' --- index.d.ts | 36 +++++++++++++++++++++++--- test/types/alt.test-d.ts | 56 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 test/types/alt.test-d.ts diff --git a/index.d.ts b/index.d.ts index 7b0b4f35..f7cc4a9d 100644 --- a/index.d.ts +++ b/index.d.ts @@ -86,10 +86,38 @@ export function after(duration: number): (value: R) => Resolved export function and(left: FutureInstance): (right: FutureInstance) => FutureInstance /** Logical or for Futures. See https://github.com/fluture-js/Fluture#alt */ -export function alt(left: FutureInstance): (right: FutureInstance) => FutureInstance - -/** Race two ConcurrentFutures. See https://github.com/fluture-js/Fluture#alt */ -export function alt(left: ConcurrentFutureInstance): (right: ConcurrentFutureInstance) => ConcurrentFutureInstance +export const alt: { + (second: F extends Never ? S : never): (first: F) => Never + (second: F extends Rejected ? S : never): (first: F) => S + (second: F extends Resolved ? S : never): (first: F) => F + + (second: Rejected): { + (first: Never): Never + (first: Rejected): Rejected + (first: Resolved): Resolved + (first: Uncertain): Uncertain + } + + (second: Uncertain): { + (first: Resolved): Resolved + (first: Rejected): Uncertain + (first: Uncertain): Uncertain + } + + (second: ConcurrentNever): (first: ConcurrentUncertain) => ConcurrentUncertain + + (second: ConcurrentRejected): { + (first: ConcurrentResolved): ConcurrentUncertain + (first: ConcurrentUncertain): ConcurrentUncertain + } + + (second: ConcurrentResolved): { + (first: ConcurrentRejected): ConcurrentUncertain + (first: ConcurrentUncertain): ConcurrentUncertain + } + + (second: ConcurrentUncertain): (first: ConcurrentUncertain) => ConcurrentUncertain +} /** Apply the function in the right Future to the value in the left Future. See https://github.com/fluture-js/Fluture#ap */ export function ap(value: FutureInstance): (apply: FutureInstance RB>) => FutureInstance diff --git a/test/types/alt.test-d.ts b/test/types/alt.test-d.ts new file mode 100644 index 00000000..c4804b7a --- /dev/null +++ b/test/types/alt.test-d.ts @@ -0,0 +1,56 @@ +import {expectType, expectError} from 'tsd'; + +import * as fl from '../../index.js'; + +const fsn: fl.FutureInstance = fl.resolve (42); +const fns: fl.FutureInstance = fl.resolve ('a'); + +// Standard usage on Future instances. +expectType (fl.alt (fl.never) (fl.never)); +expectType (fl.alt (fl.reject ('a')) (fl.never)); +expectType (fl.alt (fl.resolve ('a')) (fl.never)); +expectType (fl.alt (fl.never) (fl.reject ('a'))); +expectType> (fl.alt (fl.never) (fl.resolve ('a'))); +expectType> (fl.alt (fl.reject ('a')) (fl.resolve (42))); +expectType> (fl.alt (fl.resolve (42)) (fl.reject ('a'))); +expectType> (fl.alt (fl.resolve (42)) (fl.resolve (42))); +expectType> (fl.alt (fl.reject (42)) (fl.reject (42))); +expectType> (fl.alt (fl.reject ('a')) (fl.reject (42))); +expectType> (fl.alt (fsn) (fsn)); +expectType> (fl.alt (fl.resolve ('a')) (fl.resolve (42))); +expectError (fl.alt (fsn) (fns)); + +const x = fl.alt (fl.never) (fl.never) + +// Usage with pipe on Future instances (https://git.io/JLx3F). +expectType ((fl.never) .pipe (fl.alt (fl.never))); +expectType ((fl.never) .pipe (fl.alt (fl.reject ('a')))); +expectType ((fl.never) .pipe (fl.alt (fl.resolve ('a')))); +expectType ((fl.reject ('a')) .pipe (fl.alt (fl.never))); +expectType> ((fl.resolve ('a')) .pipe (fl.alt (fl.never))); +expectType> ((fl.resolve (42)) .pipe (fl.alt (fl.reject ('a')))); +expectType> ((fl.reject ('a')) .pipe (fl.alt (fl.resolve (42)))); +expectType> ((fl.resolve (42)) .pipe (fl.alt (fl.resolve (42)))); +expectType> ((fl.reject (42)) .pipe (fl.alt (fl.reject (42)))); +expectType> ((fl.reject (42)) .pipe (fl.alt (fl.reject ('a')))); +expectType> ((fsn) .pipe (fl.alt (fsn))); +expectType> ((fl.resolve (42)) .pipe (fl.alt (fl.resolve ('a')))); +expectError ((fns) .pipe (fl.alt (fsn))); + +const csn: fl.ConcurrentFutureInstance = fl.Par (fl.resolve (42)); +const cns: fl.ConcurrentFutureInstance = fl.Par (fl.resolve ('a')); + +// Standard usage on ConcurrentFuture instances. +expectType (fl.alt (fl.Par (fl.never)) (fl.Par (fl.never))); +expectType> (fl.alt (fl.Par (fl.reject ('a'))) (fl.Par (fl.never))); +expectType> (fl.alt (fl.Par (fl.resolve ('a'))) (fl.Par (fl.never))); +expectType> (fl.alt (fl.Par (fl.never)) (fl.Par (fl.reject ('a')))); +expectType> (fl.alt (fl.Par (fl.never)) (fl.Par (fl.resolve ('a')))); +expectType> (fl.alt (fl.Par (fl.reject ('a'))) (fl.Par (fl.resolve (42)))); +expectType> (fl.alt (fl.Par (fl.resolve (42))) (fl.Par (fl.reject ('a')))); +expectType> (fl.alt (fl.Par (fl.resolve (42))) (fl.Par (fl.resolve (42)))); +expectType> (fl.alt (fl.Par (fl.reject (42))) (fl.Par (fl.reject (42)))); +expectType> (fl.alt (csn) (csn)); +expectError (fl.alt (fl.Par (fl.resolve ('a'))) (fl.Par (fl.resolve (42)))); +expectError (fl.alt (fl.Par (fl.reject ('a'))) (fl.Par (fl.reject (42)))); +expectError (fl.alt (csn) (cns));