diff --git a/types/ramda/index.d.ts b/types/ramda/index.d.ts index 6337e08d9e..cc9616f131 100644 --- a/types/ramda/index.d.ts +++ b/types/ramda/index.d.ts @@ -420,12 +420,72 @@ declare namespace R { fn0: (x0: V0, x1: V1, x2: V2) => T1): (x0: V0, x1: V1, x2: V2) => T6; /** - * TODO composeK + * Returns the right-to-left Kleisli composition of the provided functions, each of which must return a value of a type supported by chain. + * The typings only support arrays for now. + * All functions must be unary. + * R.composeK(h, g, f) is equivalent to R.compose(R.chain(h), R.chain(g), f). */ + composeK( + fn0: (x0: V0) => T1[]): (x0: V0) => T1[]; + composeK( + fn1: (x: T1) => T2[], + fn0: (x0: V0) => T1[]): (x0: V0) => T2[]; + composeK( + fn2: (x: T2) => T3[], + fn1: (x: T1) => T2[], + fn0: (x: V0) => T1[]): (x: V0) => T3[]; + composeK( + fn3: (x: T3) => T4[], + fn2: (x: T2) => T3[], + fn1: (x: T1) => T2[], + fn0: (x: V0) => T1[]): (x: V0) => T4[]; + composeK( + fn4: (x: T4) => T5[], + fn3: (x: T3) => T4[], + fn2: (x: T2) => T3[], + fn1: (x: T1) => T2[], + fn0: (x: V0) => T1[]): (x: V0) => T5[]; + composeK( + fn5: (x: T5) => T6[], + fn4: (x: T4) => T5[], + fn3: (x: T3) => T4[], + fn2: (x: T2) => T3[], + fn1: (x: T1) => T2[], + fn0: (x: V0) => T1[]): (x: V0) => T6[]; /** - * TODO composeP + * Performs right-to-left composition of one or more Promise-returning functions. + * All functions must be unary. */ + composeP( + fn0: (x0: V0) => Promise): (x0: V0) => Promise; + composeP( + fn1: (x: T1) => Promise, + fn0: (x0: V0) => Promise): (x0: V0) => Promise; + composeP( + fn2: (x: T2) => Promise, + fn1: (x: T1) => Promise, + fn0: (x: V0) => Promise): (x: V0) => Promise; + composeP( + fn3: (x: T3) => Promise, + fn2: (x: T2) => Promise, + fn1: (x: T1) => Promise, + fn0: (x: V0) => Promise): (x: V0) => Promise; + composeP( + fn4: (x: T4) => Promise, + fn3: (x: T3) => Promise, + fn2: (x: T2) => Promise, + fn1: (x: T1) => Promise, + fn0: (x: V0) => Promise): + (x: V0) => Promise; + composeP( + fn5: (x: T5) => Promise, + fn4: (x: T4) => Promise, + fn3: (x: T3) => Promise, + fn2: (x: T2) => Promise, + fn1: (x: T1) => Promise, + fn0: (x: V0) => Promise): + (x: V0) => Promise; /** * Returns a new list consisting of the elements of the first list followed by the elements @@ -1501,6 +1561,148 @@ declare namespace R { fn8: (x: T8) => T9, fn9: (x: T9) => T10): (x0: V0, x1: V1, x2: V2) => T10; + /* + * Returns the left-to-right Kleisli composition of the provided functions, each of which must return a value of a type supported by chain. + * The typings currently support arrays only as return values. + * All functions need to be unary. + * R.pipeK(f, g, h) is equivalent to R.pipe(f, R.chain(g), R.chain(h)). + */ + pipeK( + fn0: (x0: V0) => T1[]): (x0: V0) => T1[]; + pipeK( + fn0: (x0: V0) => T1[], + fn1: (x: T1) => T2[]): (x0: V0) => T2[]; + pipeK( + fn0: (x: V0) => T1[], + fn1: (x: T1) => T2[], + fn2: (x: T2) => T3[]): (x: V0) => T3[]; + pipeK( + fn0: (x: V0) => T1[], + fn1: (x: T1) => T2[], + fn2: (x: T2) => T3[], + fn3: (x: T3) => T4[]): (x: V0) => T4[]; + pipeK( + fn0: (x: V0) => T1[], + fn1: (x: T1) => T2[], + fn2: (x: T2) => T3[], + fn3: (x: T3) => T4[], + fn4: (x: T4) => T5[]): (x: V0) => T5[]; + pipeK( + fn0: (x: V0) => T1[], + fn1: (x: T1) => T2[], + fn2: (x: T2) => T3[], + fn3: (x: T3) => T4[], + fn4: (x: T4) => T5[], + fn5: (x: T5) => T6[]): (x: V0) => T6[]; + pipeK( + fn0: (x: V0) => T1[], + fn1: (x: T1) => T2[], + fn2: (x: T2) => T3[], + fn3: (x: T3) => T4[], + fn4: (x: T4) => T5[], + fn5: (x: T5) => T6[], + fn: (x: T6) => T7[]): (x: V0) => T7[]; + pipeK( + fn0: (x: V0) => T1[], + fn1: (x: T1) => T2[], + fn2: (x: T2) => T3[], + fn3: (x: T3) => T4[], + fn4: (x: T4) => T5[], + fn5: (x: T5) => T6[], + fn6: (x: T6) => T7[], + fn: (x: T7) => T8[]): (x: V0) => T8[]; + pipeK( + fn0: (x0: V0) => T1[], + fn1: (x: T1) => T2[], + fn2: (x: T2) => T3[], + fn3: (x: T3) => T4[], + fn4: (x: T4) => T5[], + fn5: (x: T5) => T6[], + fn6: (x: T6) => T7[], + fn7: (x: T7) => T8[], + fn8: (x: T8) => T9[]): (x0: V0) => T9[]; + pipeK( + fn0: (x0: V0) => T1[], + fn1: (x: T1) => T2[], + fn2: (x: T2) => T3[], + fn3: (x: T3) => T4[], + fn4: (x: T4) => T5[], + fn5: (x: T5) => T6[], + fn6: (x: T6) => T7[], + fn7: (x: T7) => T8[], + fn8: (x: T8) => T9[], + fn9: (x: T9) => T10[]): (x0: V0) => T10[]; + + /* + * Performs left-to-right composition of one or more Promise-returning functions. + * All functions need to be unary. + */ + pipeP( + fn0: (x0: V0) => Promise): (x0: V0) => Promise; + pipeP( + fn0: (x0: V0) => Promise, + fn1: (x: T1) => Promise): (x0: V0) => Promise; + pipeP( + fn0: (x: V0) => Promise, + fn1: (x: T1) => Promise, + fn2: (x: T2) => Promise): (x: V0) => Promise; + pipeP( + fn0: (x: V0) => Promise, + fn1: (x: T1) => Promise, + fn2: (x: T2) => Promise, + fn3: (x: T3) => Promise): (x: V0) => Promise; + pipeP( + fn0: (x: V0) => Promise, + fn1: (x: T1) => Promise, + fn2: (x: T2) => Promise, + fn3: (x: T3) => Promise, + fn4: (x: T4) => Promise): (x: V0) => Promise; + pipeP( + fn0: (x: V0) => Promise, + fn1: (x: T1) => Promise, + fn2: (x: T2) => Promise, + fn3: (x: T3) => Promise, + fn4: (x: T4) => Promise, + fn5: (x: T5) => Promise): (x: V0) => Promise; + pipeP( + fn0: (x: V0) => Promise, + fn1: (x: T1) => Promise, + fn2: (x: T2) => Promise, + fn3: (x: T3) => Promise, + fn4: (x: T4) => Promise, + fn5: (x: T5) => Promise, + fn: (x: T6) => Promise): (x: V0) => Promise; + pipeP( + fn0: (x: V0) => Promise, + fn1: (x: T1) => Promise, + fn2: (x: T2) => Promise, + fn3: (x: T3) => Promise, + fn4: (x: T4) => Promise, + fn5: (x: T5) => Promise, + fn6: (x: T6) => Promise, + fn: (x: T7) => Promise): (x: V0) => Promise; + pipeP( + fn0: (x0: V0) => Promise, + fn1: (x: T1) => Promise, + fn2: (x: T2) => Promise, + fn3: (x: T3) => Promise, + fn4: (x: T4) => Promise, + fn5: (x: T5) => Promise, + fn6: (x: T6) => Promise, + fn7: (x: T7) => Promise, + fn8: (x: T8) => Promise): (x0: V0) => Promise; + pipeP( + fn0: (x0: V0) => Promise, + fn1: (x: T1) => Promise, + fn2: (x: T2) => Promise, + fn3: (x: T3) => Promise, + fn4: (x: T4) => Promise, + fn5: (x: T5) => Promise, + fn6: (x: T6) => Promise, + fn7: (x: T7) => Promise, + fn8: (x: T8) => Promise, + fn9: (x: T9) => Promise): (x0: V0) => Promise; + /** * Returns a new list by plucking the same named property off all objects in the list supplied. */ diff --git a/types/ramda/ramda-tests.ts b/types/ramda/ramda-tests.ts index 00591ebf94..32bae5fa0c 100644 --- a/types/ramda/ramda-tests.ts +++ b/types/ramda/ramda-tests.ts @@ -186,6 +186,68 @@ class F2 { const g_res: boolean = g([1, 2, 10, 13]); }; +/* composeK */ +() => { + const get = (prop: string) => (obj: any): any[] => { + const propVal = obj[prop]; + if (propVal) { + return [propVal]; + } else { + return []; + } + }; + + const getStateCode: (input: any) => any[] = R.composeK( + R.compose((val) => [val], R.toUpper), + get('state'), + get('address'), + get('user'), + ); + getStateCode({ user: { address: { state: "ny" } } }); // => [] + getStateCode({}); // => [] + + const nextThree = (num: number): number[] => ([num, num + 1, num + 2]); + const onlyOverNine = (num: number): number[] => num > 9 ? [num] : []; + const toString = (input: any): string[] => [`${input}`]; + const split = (input: string): string[] => input.split(''); + + const composed: (num: number) => string[] = R.composeK( + split, + toString, + onlyOverNine, + nextThree, + ); +}; + +/* composeP */ +() => { + interface User { + name: string; + followers: string[]; + } + interface Db { + users: { [index: string]: User }; + } + const db: Db = { + users: { + JOE: { + name: 'Joe', + followers: ['STEVE', 'SUZY'] + } + } + }; + + // We'll pretend to do a db lookup which returns a promise + const lookupUser = (userId: string): Promise => Promise.resolve(db.users[userId]); + const lookupFollowers = (user: User): Promise => Promise.resolve(user.followers); + lookupUser('JOE').then(lookupFollowers); + + // followersForUser :: String -> Promise [UserId] + const followersForUser: (input: string) => Promise = R.composeP(lookupFollowers, lookupUser); + followersForUser('JOE').then(followers => console.log('Followers:', followers)); + // Followers: ["STEVE","SUZY"] +}; + /* pipe */ () => { const func: (x: number) => string = R.pipe(double, double, shout); @@ -201,6 +263,63 @@ class F2 { const fr: number = f(3, 4); // -(3^4) + 1 }; +/* pipeK */ +() => { + const parseJson = (input: string): any[] => { + try { + return [JSON.parse(input)]; + } catch (e) { + return []; + } + }; + const get = (prop: string) => (obj: any): any[] => { + const propVal = obj[prop]; + if (propVal) { + return [propVal]; + } else { + return []; + } + }; + + const getStateCode: (input: string) => string[] = R.pipeK( + parseJson, + get('user'), + get('address'), + get('state'), + R.compose((val) => [val], R.toUpper) + ); + + getStateCode('{"user":{"address":{"state":"ny"}}}'); + // => Just('NY') + getStateCode('[Invalid JSON]'); + // => Nothing() +}; + +/* pipeP */ +() => { + interface User { + followers: string[]; + name: string; + } + + const db = { + getUserById(userName: string): Promise { + return Promise.resolve({ + name: 'Jon', + followers: [ + 'Samwell', + 'Edd', + 'Grenn', + ], + }); + }, + getFollowers(user: User): Promise { + return Promise.resolve(user.followers); + }, + }; + const followersForUser: (userName: string) => Promise = R.pipeP(db.getUserById, db.getFollowers); +}; + () => { R.invoker(1, "slice")(6, "abcdefghijklm"); R.invoker(2, "slice")(6)(8, "abcdefghijklm");