diff --git a/package.json b/package.json index eeea933..ea74bd7 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "karma-firefox-launcher": "1.1.0", "karma-jasmine": "1.1.2", "karma-mocha-reporter": "2.2.5", - "typescript": "3.0.3", + "typescript": "3.1.3", "uglify-js": "3.4.9" }, "scripts": { diff --git a/src/monet.d.ts b/src/monet.d.ts index e3de405..fee4cfc 100644 --- a/src/monet.d.ts +++ b/src/monet.d.ts @@ -1,3 +1,5 @@ +type Returns = Exclude; + // https://github.com/fantasyland/fantasy-land#setoid interface Setoid { equals(other: A): boolean; @@ -7,15 +9,15 @@ interface Setoid { /* The (covariant) functor typeclass */ // https://github.com/fantasyland/fantasy-land#functor interface Functor { - map(fn: (val: T) => V): Functor; - 'fantasy-land/map'?(fn: (val: T) => V): Functor; + map(fn: (val: T) => Returns): Functor; + 'fantasy-land/map'?(fn: (val: T) => Returns): Functor; } /* Applicative allows applying wrapped functions to wrapped elements */ // https://github.com/fantasyland/fantasy-land#applicative interface Applicative { - ap(afn: Applicative<(val: T) => V>): Applicative - 'fantasy-land/ap'?(afn: Applicative<(val: T) => V>): Applicative + ap(afn: Applicative<(val: T) => Returns>): Applicative + 'fantasy-land/ap'?(afn: Applicative<(val: T) => Returns>): Applicative } // https://github.com/fantasyland/fantasy-land#chain @@ -34,13 +36,13 @@ interface Bind extends Chain { /* Typeclass for catamorphism */ interface Catamorphism { - cata(l: (e?: F) => C, r: (v: T) => C): C; + cata(l: (e?: F) => Returns, r: (v: T) => Returns): Returns; } /* Typeclass for traversables */ export interface ITraversable { - foldLeft(initial: V): (fn: (acc: V, val: T) => V) => V; - foldRight(initial: V): (fn: (val: T, acc: V) => V) => V; + foldLeft(initial: V): (fn: (acc: V, val: T) => Returns) => Returns; + foldRight(initial: V): (fn: (val: T, acc: V) => Returns) => Returns; } /**************************************************************** @@ -52,7 +54,7 @@ interface IMonad extends Functor, Bind, Applicative { bind(fn: (val: T) => IMonad): IMonad; flatMap(fn: (val: T) => IMonad): IMonad; chain(fn: (val: T) => IMonad): IMonad; - map(fn: (val: T) => V): IMonad; + map(fn: (val: T) => Returns): IMonad; join(): IMonad; // only if T = IMonad /* These are monet-Monad-specific: */ @@ -80,7 +82,7 @@ export interface Identity extends IMonad, Setoid>, Iterable bind(fn: (val: T) => Identity): Identity; flatMap(fn: (val: T) => Identity): Identity; chain(fn: (val: T) => Identity): Identity; - map(fn: (val: T) => V): Identity; + map(fn: (val: T) => Returns): Identity; join(): Identity; // if T is Identity takeLeft(m: Identity): Identity; takeRight(m: Identity): Identity; @@ -99,7 +101,7 @@ export interface Identity extends IMonad, Setoid>, Iterable toArray(): Array; toSet(): Set; toList(): List; - to>(ctor: (iter: Iterable) => I): I; + to>(ctor: (iter: Iterable) => Returns): Returns; } interface IIdentityFactory extends IMonadFactory { @@ -126,17 +128,17 @@ export interface Maybe> bind>(fn: (val: T) => Maybe): Maybe; flatMap>(fn: (val: T) => Maybe): Maybe; chain>(fn: (val: T) => Maybe): Maybe; - map>(fn: (val: T) => V): Maybe; + map>(fn: (val: T) => Returns): Maybe; join(): T extends Maybe ? V : never; takeLeft(m: Maybe): Maybe; takeRight(m: Maybe): Maybe; /* Inherited from Applicative */ - ap>(maybeFn: Maybe<(val: T) => V>): Maybe; + ap>(maybeFn: Maybe<(val: T) => Returns>): Maybe; /* Maybe specific */ - cata(none: () => Z, some: (val: T) => Z): Z; - fold(val: V): (fn: (val: T) => V) => V; + cata(none: () => Returns, some: (val: T) => Returns): Returns; + fold(val: V): (fn: (val: T) => Returns) => Returns; catchMap(fn: () => Maybe): Maybe; filter(fn: (val: T) => boolean): Maybe; @@ -169,7 +171,7 @@ export interface Maybe> toList(): List; toEither(left?: E): Either; toValidation(fail?: E): Validation; - to>(ctor: (iter: Iterable) => I): I; + to>(ctor: (iter: Iterable) => Returns): Returns; } interface ISomeStatic extends IMonadFactory { @@ -213,22 +215,22 @@ export interface Either bind(fn: (val: T) => Either): Either; flatMap(fn: (val: T) => Either): Either; chain(fn: (val: T) => Either): Either; - map(fn: (val: T) => V): Either; + map(fn: (val: T) => Returns): Either; join(): Either; // if T is Either takeLeft(m: Either): Either; takeRight(m: Either): Either; /* Inherited from Applicative */ - ap(eitherFn: Either V>): Either; + ap(eitherFn: Either Returns>): Either; /* Either specific */ - cata(leftFn: (err: E) => Z, rightFn: (val: T) => Z): Z; - fold(leftFn: (err: E) => Z, rightFn: (val: T) => Z): Z; + cata(leftFn: (err: E) => Returns, rightFn: (val: T) => Returns): Returns; + fold(leftFn: (err: E) => Returns, rightFn: (val: T) => Returns): Returns; catchMap(fn: (err: E) => Either): Either; swap(): Either; - bimap(leftFn: (err: E) => Z, rightFn: (val: T) => V): Either; - leftMap(fn: (leftVal: E) => F): Either; + bimap(leftFn: (err: E) => Returns, rightFn: (val: T) => Returns): Either; + leftMap(fn: (leftVal: E) => Returns): Either; isRight(): boolean; isLeft(): boolean; @@ -279,7 +281,7 @@ export interface Validation bind(fn: (val: T) => Validation): Validation; flatMap(fn: (val: T) => Validation): Validation; chain(fn: (val: T) => Validation): Validation; - map(fn: (val: T) => V): Validation; + map(fn: (val: T) => Returns): Validation; join(): Validation; // if T is Validation takeLeft(m: Validation): Validation; takeRight(m: Validation): Validation; @@ -288,13 +290,13 @@ export interface Validation ap(eitherFn: Validation V>): Validation; /* Validation specific */ - cata(failFn: (fail: E) => Z, successFn: (val: T) => Z): Z; - fold(failFn: (fail: E) => Z, successFn: (val: T) => Z): Z; + cata(failFn: (fail: E) => Returns, successFn: (val: T) => Returns): Returns; + fold(failFn: (fail: E) => Returns, successFn: (val: T) => Returns): Returns; catchMap(fn: (fail: E) => Validation): Validation; swap(): Validation; - bimap(fnF: (fail: E) => F, fnS: (val: T) => V): Validation; - failMap(fn: (fail: E) => F): Validation; + bimap(fnF: (fail: E) => Returns, fnS: (val: T) => Returns): Validation; + failMap(fn: (fail: E) => Returns): Validation; isSuccess(): boolean; isFail(): boolean; @@ -343,13 +345,13 @@ export interface List extends IMonad, Setoid>, ITraversable, It bind(fn: (val: T) => List): List; flatMap(fn: (val: T) => List): List; chain(fn: (val: T) => List): List; - map(fn: (val: T) => V): List; + map(fn: (val: T) => Returns): List; join(): List; // if T is List takeLeft(m: List): List; takeRight(m: List): List; /* Inherited from Applicative */ - ap(listFn: List<(val: T) => V>): List; + ap(listFn: List<(val: T) => Returns>): List; /* List specific */ filter(fn: (val: T) => boolean): List; @@ -387,7 +389,7 @@ export interface List extends IMonad, Setoid>, ITraversable, It toArray(): Array; toSet(): Set; - to>(ctor: (iter: Iterable) => I): I; + to>(ctor: (iter: Iterable) => Returns): Returns; } export interface Nil extends List { @@ -424,7 +426,7 @@ export interface NEL extends IMonad, Setoid>, ITraversable, Iter bind(fn: (val: T) => NEL): NEL; flatMap(fn: (val: T) => NEL): NEL; chain(fn: (val: T) => NEL): NEL; - map(fn: (val: T) => V): NEL; + map(fn: (val: T) => Returns): NEL; join(): NEL; // if T is NEL | List takeLeft(m: NEL): NEL; takeRight(m: NEL): NEL; @@ -438,10 +440,10 @@ export interface NEL extends IMonad, Setoid>, ITraversable, Iter extract(): T; // alias for head /* Inherited from Applicative */ - ap(listFn: NEL<(val: T) => V>): NEL; + ap(listFn: NEL<(val: T) => Returns>): NEL; /* NEL specific */ - reduceLeft(fn: (acc: T, element: T) => T): T; + reduceLeft(fn: (acc: T, element: T) => Returns): Returns; filter(fn: (val: T) => boolean): List; filterNot(fn: (val: T) => boolean): List; @@ -467,7 +469,7 @@ export interface NEL extends IMonad, Setoid>, ITraversable, Iter toArray(): Array; toList(): List; toSet(): Set; - to>(ctor: (iter: Iterable) => I): I; + to>(ctor: (iter: Iterable) => Returns): Returns; } export type NonEmptyList = NEL; @@ -499,13 +501,13 @@ export interface IO extends IMonad { bind(fn: (val: T) => IO): IO; flatMap(fn: (val: T) => IO): IO; chain(fn: (val: T) => IO): IO; - map(fn: (v: T) => V): IO; + map(fn: (v: T) => Returns): IO; join(): IO; // if T is IO takeLeft(m: IO): IO; takeRight(m: IO): IO; /* Inherited from Applicative: */ - ap(ioFn: IO<(v: T) => V>): IO; + ap(ioFn: IO<(v: T) => Returns>): IO; /* IO specific: */ run(): T; @@ -537,7 +539,7 @@ export interface Reader extends IMonad { bind(fn: (val: A) => Reader): Reader; flatMap(fn: (val: A) => Reader): Reader; chain(fn: (val: A) => Reader): Reader; - map(fn: (val: A) => B): Reader; + map(fn: (val: A) => Returns): Reader; join(): Reader; // if A is Reader takeLeft(m: Reader): Reader; takeRight(m: Reader): Reader; @@ -545,11 +547,11 @@ export interface Reader extends IMonad { /* Reader-specific: */ run(config: E): A; - local(fn: (val: X) => E): Reader; + local(fn: (val: X) => Returns): Reader; } interface IReaderFactory extends IMonadFactory { - (fn: (env: E) => A): Reader; + (fn: (env: E) => Returns): Reader; } interface IReaderStatic extends IReaderFactory, IMonadStatic { @@ -588,7 +590,7 @@ export interface Free extends IMonad { flatMap(fn: (val: A) => Free): Free; chain(fn: (val: A) => Free): Free; join(): Free; // only if A = Free on the same functor - map(fn: (val: A) => V): Free; + map(fn: (val: A) => Returns): Free; takeLeft(other: Free): Free; takeRight(other: Free): Free; diff --git a/test/typings/either-spec.ts b/test/typings/either-spec.ts index 8adb666..28bea7c 100644 --- a/test/typings/either-spec.ts +++ b/test/typings/either-spec.ts @@ -74,4 +74,9 @@ const oops: Either = Either.left("oops"); console.assert(twelve.right() === 12); console.assert(oops.left() === "oops"); +// uncomment to fail typecheck for non return value +// twelve.map(() => { "no return"; }); +// twelve.leftMap(() => { "no return"; }); +// twelve.cata(() => { "no return" }, () => { "no return"; }); + console.log(nameError, messageCopy); diff --git a/tsconfig.json b/tsconfig.json index 8dcf08d..0ed643f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,18 +3,12 @@ "listFiles": true, "lib": ["dom", "es5", "es2015.collection", "es2015.iterable"], "noEmit": true, - "noImplicitAny": true, + "noErrorTruncation": true, + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, "strict": true }, - "files": [ - "test/typings/identity-spec.ts", - "test/typings/maybe-spec.ts", - "test/typings/either-spec.ts", - "test/typings/validation-spec.ts", - "test/typings/list-spec.ts", - "test/typings/nel-spec.ts", - "test/typings/io-spec.ts", - "test/typings/reader-spec.ts", - "test/typings/free-spec.ts" + "include": [ + "test/typings/*" ] }