From 1137b8aa356b43cd901d7288df0c4c9758fa638e Mon Sep 17 00:00:00 2001 From: Kevin Li Date: Tue, 4 Jul 2017 19:53:53 -0700 Subject: [PATCH] fix: use generic self-types getOrElse and orElse use self-types in order to support typed upper bounds.[0] In TypeScript 2.4, generic functions were checked more strictly[1]. This causes the implicit downward type cast to fail, so we explicitly invoke the cast in the method body. This workaround is backwards-compatible with TypeScript 2.3. Bounded polymorphism has been implemented[2], but true F-bounded polymorphism hasn't been. This means a type like interface Option> is invalid. Alternatively, we can solve this with a lower type bound, but these don't work against concrete classes[3]. --- We should also upgrade monapt's TypeScript dependency to 2.4, but there are unrelated errors compiling the tests. [0] https://github.com/Microsoft/TypeScript/issues/13337 [1] https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#stricter-checking-for-generic-functions [2] https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#type-parameters-as-constraints [3] https://github.com/Microsoft/TypeScript/issues/14520 --- src/option/none.ts | 4 ++-- src/option/some.ts | 12 ++++++++---- src/try/failure.ts | 4 ++-- src/try/success.ts | 12 ++++++++---- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/option/none.ts b/src/option/none.ts index 415bff7..18e5f4c 100644 --- a/src/option/none.ts +++ b/src/option/none.ts @@ -47,7 +47,7 @@ class None_ implements Option { throw new Option.NoSuchElementError(); } - getOrElse(this: None_, defaultValue: () => B): B { + getOrElse(this: Option, defaultValue: () => B): B { return defaultValue(); } @@ -59,7 +59,7 @@ class None_ implements Option { return matcher.None(); } - orElse(this: None_, alternative: () => Option): Option { + orElse(this: Option, alternative: () => Option): Option { return alternative(); } } diff --git a/src/option/some.ts b/src/option/some.ts index 67b8c88..7b5180b 100644 --- a/src/option/some.ts +++ b/src/option/some.ts @@ -53,8 +53,10 @@ class Some implements Option { return this.value; } - getOrElse(this: Some, defaultValue: () => B): B { - return this.value; + getOrElse(this: Option, defaultValue: () => B): B { + const self: Some = this as Some; + + return self.value; } map(mapper: (value: A) => B): Option { @@ -65,8 +67,10 @@ class Some implements Option { return matcher.Some(this.value); } - orElse(this: Some, alternative: () => Option): Option { - return this; + orElse(this: Option, alternative: () => Option): Option { + const self: Some = this as Some; + + return self; } } diff --git a/src/try/failure.ts b/src/try/failure.ts index 39937aa..da5e78d 100644 --- a/src/try/failure.ts +++ b/src/try/failure.ts @@ -45,7 +45,7 @@ class Failure implements Try { throw this.error; } - getOrElse(this: Failure, defaultValue: () => B): B { + getOrElse(this: Try, defaultValue: () => B): B { return defaultValue(); } @@ -57,7 +57,7 @@ class Failure implements Try { return matcher.Failure(this.error); } - orElse(this: Failure, alternative: () => Try): Try { + orElse(this: Try, alternative: () => Try): Try { return alternative(); } diff --git a/src/try/success.ts b/src/try/success.ts index 68b91e1..95dd3c2 100644 --- a/src/try/success.ts +++ b/src/try/success.ts @@ -46,8 +46,10 @@ class Success implements Try { return this.value; } - getOrElse(this: Success, defaultValue: () => B): B { - return this.value; + getOrElse(this: Try, defaultValue: () => B): B { + const self: Success = this as Success; + + return self.value; } map(f: (value: A) => B): Try { @@ -58,8 +60,10 @@ class Success implements Try { return matcher.Success(this.value); } - orElse(this: Success, alternative: () => Try): Try { - return this; + orElse(this: Try, alternative: () => Try): Try { + const self: Success = this as Success; + + return self; } recover(fn: (error: Error) => A): Try {