monet / monet.js

monet.js - Monadic types library for JavaScript
https://monet.github.io/monet.js/
MIT License
1.6k stars 114 forks source link

Type 'V' does not satisfy the constraint '{}' #254

Open cyrildever opened 2 years ago

cyrildever commented 2 years ago

When upgrading TypeScript to version 4.8.x, I have the following compilation errors:

node_modules/monet/dist/monet.d.ts:132:30 - error TS2344: Type 'V' does not satisfy the constraint '{}'.

132   join<V>(): T extends Maybe<V> ? V : never;
                                 ~

  node_modules/monet/dist/monet.d.ts:132:8
    132   join<V>(): T extends Maybe<V> ? V : never;
               ~
    This type parameter might need an `extends {}` constraint.

node_modules/monet/dist/monet.d.ts:181:24 - error TS2344: Type 'V' does not satisfy the constraint '{}'.

181   <V>(value: V): Maybe<V>;
                           ~

  node_modules/monet/dist/monet.d.ts:181:4
    181   <V>(value: V): Maybe<V>;
           ~
    This type parameter might need an `extends {}` constraint.

node_modules/monet/dist/monet.d.ts:185:16 - error TS2344: Type 'V' does not satisfy the constraint '{}'.

185   <V>(): Maybe<V>;
                   ~

  node_modules/monet/dist/monet.d.ts:185:4
    185   <V>(): Maybe<V>;
           ~
    This type parameter might need an `extends {}` constraint.

node_modules/monet/dist/monet.d.ts:195:46 - error TS2344: Type 'V' does not satisfy the constraint '{}'.

195   fromFalsy<V>(val: V|null|undefined): Maybe<V>;
                                                 ~

  node_modules/monet/dist/monet.d.ts:195:13
    195   fromFalsy<V>(val: V|null|undefined): Maybe<V>;
                    ~
    This type parameter might need an `extends {}` constraint.

node_modules/monet/dist/monet.d.ts:196:45 - error TS2344: Type 'V' does not satisfy the constraint '{}'.

196   fromNull<V>(val: V|null|undefined): Maybe<V>;
                                                ~

  node_modules/monet/dist/monet.d.ts:196:12
    196   fromNull<V>(val: V|null|undefined): Maybe<V>;
                   ~
    This type parameter might need an `extends {}` constraint.

node_modules/monet/dist/monet.d.ts:197:45 - error TS2344: Type 'V' does not satisfy the constraint '{}'.

197   fromUndefined<V>(val: V|undefined): Maybe<V>;
                                                ~

  node_modules/monet/dist/monet.d.ts:197:17
    197   fromUndefined<V>(val: V|undefined): Maybe<V>;
                        ~
    This type parameter might need an `extends {}` constraint.

node_modules/monet/dist/monet.d.ts:198:46 - error TS2344: Type 'V' does not satisfy the constraint '{}'.

198   fromEmpty<V>(val: V|null|undefined): Maybe<V>;
                                                 ~

  node_modules/monet/dist/monet.d.ts:198:13
    198   fromEmpty<V>(val: V|null|undefined): Maybe<V>;
                    ~
    This type parameter might need an `extends {}` constraint.

node_modules/monet/dist/monet.d.ts:248:20 - error TS2344: Type 'T' does not satisfy the constraint '{}'.

248   toMaybe(): Maybe<T>;
                       ~

  node_modules/monet/dist/monet.d.ts:216:28
    216 export interface Either<E, T>
                                   ~
    This type parameter might need an `extends {}` constraint.

node_modules/monet/dist/monet.d.ts:320:20 - error TS2344: Type 'T' does not satisfy the constraint '{}'.

320   toMaybe(): Maybe<T>;
                       ~

  node_modules/monet/dist/monet.d.ts:286:32
    286 export interface Validation<E, T>
                                       ~
    This type parameter might need an `extends {}` constraint.

node_modules/monet/dist/monet.d.ts:376:28 - error TS2344: Type 'T' does not satisfy the constraint '{}'.

376   lookup(i: number): Maybe<T>;
                               ~

  node_modules/monet/dist/monet.d.ts:352:23
    352 export interface List<T> extends IMonad<T>, Setoid<List<T>>, ITraversable<T>, Iterable<T> {
                              ~
    This type parameter might need an `extends {}` constraint.

node_modules/monet/dist/monet.d.ts:384:38 - error TS2344: Type 'V' does not satisfy the constraint '{}'.

384   flattenMaybe<V>(): T extends Maybe<V> ? List<V> : never;
                                         ~

  node_modules/monet/dist/monet.d.ts:384:16
    384   flattenMaybe<V>(): T extends Maybe<V> ? List<V> : never;
                       ~
    This type parameter might need an `extends {}` constraint.

node_modules/monet/dist/monet.d.ts:463:40 - error TS2344: Type 'T' does not satisfy the constraint '{}'.

463   find(fn: (val: T) => boolean): Maybe<T>;
                                           ~

  node_modules/monet/dist/monet.d.ts:436:22
    436 export interface NEL<T> extends IMonad<T>, Setoid<NEL<T>>, ITraversable<T>, Iterable<T> {
                             ~
    This type parameter might need an `extends {}` constraint.

node_modules/monet/dist/monet.d.ts:469:28 - error TS2344: Type 'T' does not satisfy the constraint '{}'.

469   lookup(i: number): Maybe<T>;
                               ~

  node_modules/monet/dist/monet.d.ts:436:22
    436 export interface NEL<T> extends IMonad<T>, Setoid<NEL<T>>, ITraversable<T>, Iterable<T> {
                             ~
    This type parameter might need an `extends {}` constraint.

node_modules/monet/dist/monet.d.ts:482:38 - error TS2344: Type 'V' does not satisfy the constraint '{}'.

482   flattenMaybe<V>(): T extends Maybe<V> ? List<V> : never;
                                         ~

  node_modules/monet/dist/monet.d.ts:482:16
    482   flattenMaybe<V>(): T extends Maybe<V> ? List<V> : never;
                       ~
    This type parameter might need an `extends {}` constraint.

Found 14 errors in the same file, starting at: node_modules/monet/dist/monet.d.ts:132
tyilo commented 2 years ago

It doesn't actually happen with typescript 4.7.4 only with 4.8.x.

cyrildever commented 2 years ago

You're totally right. It only happens with 4.8.x. I didn't clean up my package-lock.json when testing with 4.7.4.

cyrildever commented 2 years ago

@Tyilo I changed it in my initial comment so that it doesn't mislead others.

alexanderbartl commented 1 year ago

Yes, monet.js is currently incompatible with TypeScript 4.8, at least in strict mode. You can find some background on the change in TypeScript 4.8 in the announcement blogpost. Unfortunately, the fix is not as easy as just adding extends {} to every generic, so someone with a better understanding of the library/types will need to look into this.

cyrildever commented 1 year ago

Unfortunately, the fix is not as easy as just adding extends {} to every generic, so someone with a better understanding of the library/types will need to look into this.

Indeed. I tried a few things after cloning the repo and they all go down to the problem that, in the Maybe<T> interface, T extends NonNullable. Therefore, I agree with you that it needs someone with a deep understanding of the types to work it out.

FYI: There is a quick and dirty fix but it's at the cost of removing this dependency on the NonNullable type: (at line 125 of src/monet.d.ts file)

-export interface Maybe<T extends NonNullable<{}>>
-  extends Setoid<Maybe<T>>, ITraversable<T>, Catamorphism<undefined, T>, Iterable<T> {
+export interface Maybe<T>
+  extends Setoid<Maybe<T>>, ITraversable<T>, Catamorphism<NonNullable<T>, T>, Iterable<T> {
   /* Inherited from Monad: */
-  bind<V extends NonNullable<{}>>(fn: (val: T) => Maybe<V>): Maybe<V>;
-  flatMap<V extends NonNullable<{}>>(fn: (val: T) => Maybe<V>): Maybe<V>;
-  chain<V extends NonNullable<{}>>(fn: (val: T) => Maybe<V>): Maybe<V>;
-  map<V extends NonNullable<{}>>(fn: (val: T) => V): Maybe<V>;
+  bind<V>(fn: (val: T) => Maybe<V>): Maybe<V>;
+  flatMap<V>(fn: (val: T) => Maybe<V>): Maybe<V>;
+  chain<V>(fn: (val: T) => Maybe<V>): Maybe<V>;
+  map<V>(fn: (val: T) => V): Maybe<V>;
   join<V>(): T extends Maybe<V> ? V : never;
   takeLeft(m: Maybe<T>): Maybe<T>;
   takeRight(m: Maybe<T>): Maybe<T>;

   /* Inherited from Applicative */
-  ap<V extends NonNullable<{}>>(maybeFn: Maybe<(val: T) => V>): Maybe<V>;
-  apTo<V extends NonNullable<{}>> (value: Maybe<V>): T extends (arg: V) => any ? Maybe<ReturnType<T>> : never;
+  ap<V>(maybeFn: Maybe<(val: T) => V>): Maybe<V>;
+  apTo<V>(value: Maybe<V>): T extends (arg: V) => any ? Maybe<ReturnType<T>> : never;
lieutdan13 commented 1 year ago

This incompatibility is preventing us from upgrading TypeScript. Can a maintainer review the proposed Pull Request #255 to see if this is a viable fix? Alternatively, does anyone have any suggestions for alternatives to the monet package, specifically a replacement for Either?

cyrildever commented 1 year ago

This incompatibility is preventing us from upgrading TypeScript. Can a maintainer review the proposed Pull Request #255 to see if this is a viable fix? Alternatively, does anyone have any suggestions for alternatives to the monet package, specifically a replacement for Either?

For this reason, I had to re-write it and put it in my own utility library: ts-utls Feel free to use it.

$ npm i ts-utls
import { Either } from 'ts-utls'

const eitherString = Either('string', true)
console.assert(eitherString.isRight())
console.assert(eitherString.right() === 'string')
const rightString = Right('right')
console.assert(rightString.equals(eitherString))