From 2af6bee5663253a2cfb9d57191362d9ececbc56d Mon Sep 17 00:00:00 2001 From: Sila Setthakan-anan Date: Tue, 20 Feb 2024 19:20:20 -0800 Subject: [PATCH] fix: Improve type inference for `chain` function (#370) --- cdn/radash.esm.js | 8 ++++--- cdn/radash.js | 8 ++++--- cdn/radash.min.js | 2 +- docs/curry/chain.mdx | 37 ++++++++++++++++++++++++++---- src/curry.ts | 51 +++++++++++++++++++++++++++++++++++++---- src/tests/curry.test.ts | 47 ++++++++++++++++++++++++++++++++++++- 6 files changed, 136 insertions(+), 17 deletions(-) diff --git a/cdn/radash.esm.js b/cdn/radash.esm.js index 1b52d598..4b6ce7cf 100644 --- a/cdn/radash.esm.js +++ b/cdn/radash.esm.js @@ -486,9 +486,11 @@ const guard = (func, shouldGuard) => { } }; -const chain = (...funcs) => (...args) => { - return funcs.slice(1).reduce((acc, fn) => fn(acc), funcs[0](...args)); -}; +function chain(...funcs) { + return function forInitialArg(initialArg) { + return funcs.reduce((acc, fn) => fn(acc), initialArg); + }; +} const compose = (...funcs) => { return funcs.reverse().reduce((acc, fn) => fn(acc)); }; diff --git a/cdn/radash.js b/cdn/radash.js index 154f554c..58be43be 100644 --- a/cdn/radash.js +++ b/cdn/radash.js @@ -489,9 +489,11 @@ var radash = (function (exports) { } }; - const chain = (...funcs) => (...args) => { - return funcs.slice(1).reduce((acc, fn) => fn(acc), funcs[0](...args)); - }; + function chain(...funcs) { + return function forInitialArg(initialArg) { + return funcs.reduce((acc, fn) => fn(acc), initialArg); + }; + } const compose = (...funcs) => { return funcs.reverse().reduce((acc, fn) => fn(acc)); }; diff --git a/cdn/radash.min.js b/cdn/radash.min.js index 851cd16d..efc40c7a 100644 --- a/cdn/radash.min.js +++ b/cdn/radash.min.js @@ -1 +1 @@ -var radash=function(u){"use strict";const E=t=>!!t&&t.constructor===Symbol,w=Array.isArray,k=t=>!!t&&t.constructor===Object,N=t=>t==null||typeof t!="object"&&typeof t!="function",y=t=>!!(t&&t.constructor&&t.call&&t.apply),K=t=>typeof t=="string"||t instanceof String,W=t=>h(t)&&t%1===0,J=t=>h(t)&&t%1!==0,h=t=>{try{return Number(t)===t}catch{return!1}},T=t=>Object.prototype.toString.call(t)==="[object Date]",j=t=>!(!t||!t.then||!y(t.then)),X=t=>{if(t===!0||t===!1||t==null)return!0;if(h(t))return t===0;if(T(t))return isNaN(t.getTime());if(y(t)||E(t))return!1;const e=t.length;if(h(e))return e===0;const n=t.size;return h(n)?n===0:Object.keys(t).length===0},z=(t,e)=>{if(Object.is(t,e))return!0;if(t instanceof Date&&e instanceof Date)return t.getTime()===e.getTime();if(t instanceof RegExp&&e instanceof RegExp)return t.toString()===e.toString();if(typeof t!="object"||t===null||typeof e!="object"||e===null)return!1;const n=Reflect.ownKeys(t),r=Reflect.ownKeys(e);if(n.length!==r.length)return!1;for(let s=0;st.reduce((n,r)=>{const s=e(r);return n[s]||(n[s]=[]),n[s].push(r),n},{});function H(...t){return!t||!t.length?[]:new Array(Math.max(...t.map(({length:e})=>e))).fill([]).map((e,n)=>t.map(r=>r[n]))}function Q(t,e){if(!t||!t.length)return{};const n=y(e)?e:w(e)?(r,s)=>e[s]:(r,s)=>e;return t.reduce((r,s,i)=>(r[s]=n(s,i),r),{})}const O=(t,e)=>!t||(t.length??0)===0?null:t.reduce(e),V=(t,e)=>(t||[]).reduce((n,r)=>n+(e?e(r):r),0),G=(t,e=void 0)=>t?.length>0?t[0]:e,x=(t,e=void 0)=>t?.length>0?t[t.length-1]:e,S=(t,e,n=!1)=>{if(!t)return[];const r=(i,c)=>e(i)-e(c),s=(i,c)=>e(c)-e(i);return t.slice().sort(n===!0?s:r)},tt=(t,e,n="asc")=>{if(!t)return[];const r=(i,c)=>`${e(i)}`.localeCompare(e(c)),s=(i,c)=>`${e(c)}`.localeCompare(e(i));return t.slice().sort(n==="desc"?s:r)},et=(t,e)=>t?t.reduce((n,r)=>{const s=e(r);return n[s]=(n[s]??0)+1,n},{}):{},nt=(t,e,n)=>{if(!t)return[];if(e===void 0)return[...t];for(let r=0;rr)=>t.reduce((r,s)=>(r[e(s)]=n(s),r),{}),rt=(t,e,n)=>t?t.reduce((r,s,i)=>(n(s,i)&&r.push(e(s,i)),r),[]):[];function st(t,e){const n=e??(r=>r);return O(t,(r,s)=>n(r)>n(s)?r:s)}function ut(t,e){const n=e??(r=>r);return O(t,(r,s)=>n(r){const n=Math.ceil(t.length/e);return new Array(n).fill(null).map((r,s)=>t.slice(s*e,s*e+e))},ct=(t,e)=>{const n=t.reduce((r,s)=>{const i=e?e(s):s;return r[i]||(r[i]=s),r},{});return Object.values(n)};function*A(t,e,n=s=>s,r=1){const s=y(n)?n:()=>n,i=e?t:0,c=e??t;for(let o=i;o<=c&&(yield s(o),!(o+r>c));o+=r);}const C=(t,e,n,r)=>Array.from(A(t,e,n,r)),ot=t=>t.reduce((e,n)=>(e.push(...n),e),[]),lt=(t,e,n)=>{if(!t||!e)return!1;const r=n??(i=>i),s=e.reduce((i,c)=>(i[r(c)]=!0,i),{});return t.some(i=>s[r(i)])},L=(t,e)=>t?t.reduce((n,r)=>{const[s,i]=n;return e(r)?[[...s,r],i]:[s,[...i,r]]},[[],[]]):[[],[]],ft=(t,e,n)=>!e&&!t?[]:e?t?n?t.reduce((r,s)=>{const i=e.find(c=>n(s)===n(c));return i?r.push(i):r.push(s),r},[]):t:[]:t,at=(t,e,n)=>{if(!t&&!e)return[];if(!e)return[...t];if(!t)return[e];for(let r=0;r{if(!t&&!e)return[];if(!t)return[e];if(!e)return[...t];const s=n?(o,a)=>n(o,a)===n(e,a):o=>o===e;return t.find(s)?t.filter((o,a)=>!s(o,a)):(r?.strategy??"append")==="append"?[...t,e]:[e,...t]},gt=t=>t?.filter(e=>!!e)??[],M=(t,e,n)=>{let r=n;for(let s=1;s<=t;s++)r=e(r,s);return r},ht=(t,e,n=r=>r)=>{if(!t?.length&&!e?.length)return[];if(t?.length===void 0)return[...e];if(!e?.length)return[...t];const r=e.reduce((s,i)=>(s[n(i)]=!0,s),{});return t.filter(s=>!r[n(s)])};function mt(t,e){if(t.length===0)return t;const n=e%t.length;return n===0?t:[...t.slice(-n,t.length),...t.slice(0,-n)]}const wt=async(t,e,n)=>{const r=n!==void 0;if(!r&&t?.length<1)throw new Error("Cannot reduce empty array with no init value");const s=r?t:t.slice(1);let i=r?n:t[0];for(const[c,o]of s.entries())i=await e(i,o,c);return i},yt=async(t,e)=>{if(!t)return[];let n=[],r=0;for(const s of t){const i=await e(s,r++);n.push(i)}return n},pt=async t=>{const e=[],n=(i,c)=>e.push({fn:i,rethrow:c?.rethrow??!1}),[r,s]=await m(t)(n);for(const{fn:i,rethrow:c}of e){const[o]=await m(i)(r);if(o&&c)throw o}if(r)throw r;return s};class Z extends Error{constructor(e=[]){super();const n=e.find(r=>r.name)?.name??"";this.name=`AggregateError(${n}...)`,this.message=`AggregateError with ${e.length} errors`,this.stack=e.find(r=>r.stack)?.stack??this.stack,this.errors=e}}const bt=async(t,e,n)=>{const r=e.map((d,b)=>({index:b,item:d})),s=async d=>{const b=[];for(;;){const l=r.pop();if(!l)return d(b);const[f,g]=await m(n)(l.item);b.push({error:f,result:g,index:l.index})}},i=C(1,t).map(()=>new Promise(s)),c=await Promise.all(i),[o,a]=L(S(c.flat(),d=>d.index),d=>!!d.error);if(o.length>0)throw new Z(o.map(d=>d.error));return a.map(d=>d.result)};async function kt(t){const e=w(t)?t.map(s=>[null,s]):Object.entries(t),n=await Promise.all(e.map(([s,i])=>i.then(c=>({result:c,exc:null,key:s})).catch(c=>({result:null,exc:c,key:s})))),r=n.filter(s=>s.exc);if(r.length>0)throw new Z(r.map(s=>s.exc));return w(t)?n.map(s=>s.result):n.reduce((s,i)=>({...s,[i.key]:i.result}),{})}const Ot=async(t,e)=>{const n=t?.times??3,r=t?.delay,s=t?.backoff??null;for(const i of A(1,n)){const[c,o]=await m(e)(a=>{throw{_exited:a}});if(!c)return o;if(c._exited)throw c._exited;if(i===n)throw c;r&&await $(r),s&&await $(s(i))}},$=t=>new Promise(e=>setTimeout(e,t)),m=t=>(...e)=>{try{const n=t(...e);return j(n)?n.then(r=>[void 0,r]).catch(r=>[r,void 0]):[void 0,n]}catch(n){return[n,void 0]}},At=(t,e)=>{const n=s=>{if(e&&!e(s))throw s},r=s=>s instanceof Promise;try{const s=t();return r(s)?s.catch(n):s}catch(s){return n(s)}},Ct=(...t)=>(...e)=>t.slice(1).reduce((n,r)=>r(n),t[0](...e)),$t=(...t)=>t.reverse().reduce((e,n)=>n(e)),Pt=(t,...e)=>(...n)=>t(...e,...n),_t=(t,e)=>n=>t({...e,...n}),Et=t=>new Proxy({},{get:(e,n)=>t(n)}),Nt=(t,e,n,r)=>function(...i){const c=n?n(...i):JSON.stringify({args:i}),o=t[c];if(o!==void 0&&(!o.exp||o.exp>new Date().getTime()))return o.value;const a=e(...i);return t[c]={exp:r?new Date().getTime()+r:null,value:a},a},Tt=(t,e={})=>Nt({},t,e.key??null,e.ttl??null),jt=({delay:t},e)=>{let n,r=!0;const s=(...i)=>{r?(clearTimeout(n),n=setTimeout(()=>{r&&e(...i),n=void 0},t)):e(...i)};return s.isPending=()=>n!==void 0,s.cancel=()=>{r=!1},s.flush=(...i)=>e(...i),s},zt=({interval:t},e)=>{let n=!0,r;const s=(...i)=>{n&&(e(...i),n=!1,r=setTimeout(()=>{n=!0,r=void 0},t))};return s.isThrottled=()=>r!==void 0,s},St=(t,e)=>{const n=()=>{};return new Proxy(Object.assign(n,t),{get:(r,s)=>r[s],set:(r,s,i)=>(r[s]=i,!0),apply:(r,s,i)=>e(Object.assign({},r))(...i)})},Bt=(t,e)=>{const n=e===void 0?0:e;if(t==null)return n;const r=parseFloat(t);return isNaN(r)?n:r},D=(t,e)=>{const n=e===void 0?0:e;if(t==null)return n;const r=parseInt(t);return isNaN(r)?n:r},Lt=(t,e=n=>n===void 0)=>t?Object.keys(t).reduce((r,s)=>(e(t[s])||(r[s]=t[s]),r),{}):{},P=(t,e)=>Object.keys(t).reduce((r,s)=>(r[e(s,t[s])]=t[s],r),{}),Mt=(t,e)=>Object.keys(t).reduce((r,s)=>(r[s]=e(t[s],s),r),{}),Zt=(t,e)=>t?Object.entries(t).reduce((n,[r,s])=>{const[i,c]=e(r,s);return n[i]=c,n},{}):{},Dt=t=>t?Object.keys(t).reduce((n,r)=>(n[t[r]]=r,n),{}):{},Ft=t=>P(t,e=>e.toLowerCase()),Rt=t=>P(t,e=>e.toUpperCase()),F=t=>{if(N(t))return t;if(typeof t=="function")return t.bind({});const e=new t.constructor;return Object.getOwnPropertyNames(t).forEach(n=>{e[n]=t[n]}),e},It=(t,e)=>{if(!t)return[];const n=Object.entries(t);return n.length===0?[]:n.reduce((r,s)=>(r.push(e(s[0],s[1])),r),[])},qt=(t,e)=>t?e.reduce((n,r)=>(Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]),n),{}):{},vt=(t,e)=>t?!e||e.length===0?t:e.reduce((n,r)=>(delete n[r],n),{...t}):{},R=(t,e,n)=>{const r=e.split(/[\.\[\]]/g);let s=t;for(let i of r){if(s===null||s===void 0)return n;i=i.replace(/['"]/g,""),i.trim()!==""&&(s=s[i])}return s===void 0?n:s},I=(t,e,n)=>{if(!t)return{};if(!e||n===void 0)return t;const r=e.split(/[\.\[\]]/g).filter(c=>!!c.trim()),s=c=>{if(r.length>1){const o=r.shift(),a=D(r[0],null)!==null;c[o]=c[o]===void 0?a?[]:{}:c[o],s(c[o])}else c[r[0]]=n},i=F(t);return s(i),i},q=(t,e)=>!t||!e?t??e??{}:Object.entries({...t,...e}).reduce((n,[r,s])=>({...n,[r]:(()=>k(t[r])?q(t[r],s):s)()}),{}),v=t=>{if(!t)return[];const e=(n,r)=>k(n)?Object.entries(n).flatMap(([s,i])=>e(i,[...r,s])):w(n)?n.flatMap((s,i)=>e(s,[...r,`${i}`])):[r.join(".")];return e(t,[])},Ut=t=>t?B(v(t),e=>e,e=>R(t,e)):{},Kt=t=>t?Object.keys(t).reduce((e,n)=>I(e,n,t[n]),{}):{},_=(t,e)=>Math.floor(Math.random()*(e-t+1)+t),Wt=t=>{const e=t.length;if(e===0)return null;const n=_(0,e-1);return t[n]},Jt=t=>t.map(e=>({rand:Math.random(),value:e})).sort((e,n)=>e.rand-n.rand).map(e=>e.value),Xt=(t,e="")=>{const n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"+e;return M(t,r=>r+n.charAt(_(0,n.length-1)),"")},Yt=(t,e=n=>`${n}`)=>{const{indexesByKey:n,itemsByIndex:r}=t.reduce((l,f,g)=>({indexesByKey:{...l.indexesByKey,[e(f)]:g},itemsByIndex:{...l.itemsByIndex,[g]:f}}),{indexesByKey:{},itemsByIndex:{}}),s=(l,f)=>n[e(l)]n[e(l)]>n[e(f)]?l:f,c=()=>r[0],o=()=>r[t.length-1],a=(l,f)=>r[n[e(l)]+1]??f??c(),d=(l,f)=>r[n[e(l)]-1]??f??o();return{min:s,max:i,first:c,last:o,next:a,previous:d,spin:(l,f)=>{if(f===0)return l;const g=Math.abs(f),ne=g>t.length?g%t.length:g;return C(0,ne-1).reduce(U=>f>0?a(U):d(U),l)}}},p=t=>{if(!t||t.length===0)return"";const e=t.toLowerCase();return e.substring(0,1).toUpperCase()+e.substring(1,e.length)},Ht=t=>{const e=t?.replace(/([A-Z])+/g,p)?.split(/(?=[A-Z])|[\.\-\s_]/).map(n=>n.toLowerCase())??[];return e.length===0?"":e.length===1?e[0]:e.reduce((n,r)=>`${n}${r.charAt(0).toUpperCase()}${r.slice(1)}`)},Qt=(t,e)=>{const n=t?.replace(/([A-Z])+/g,p).split(/(?=[A-Z])|[\.\-\s_]/).map(s=>s.toLowerCase())??[];if(n.length===0)return"";if(n.length===1)return n[0];const r=n.reduce((s,i)=>`${s}_${i.toLowerCase()}`);return e?.splitOnNumber===!1?r:r.replace(/([A-Za-z]{1}[0-9]{1})/,s=>`${s[0]}_${s[1]}`)},Vt=t=>{const e=t?.replace(/([A-Z])+/g,p)?.split(/(?=[A-Z])|[\.\-\s_]/).map(n=>n.toLowerCase())??[];return e.length===0?"":e.length===1?e[0]:e.reduce((n,r)=>`${n}-${r.toLowerCase()}`)},Gt=t=>{const e=t?.split(/[\.\-\s_]/).map(n=>n.toLowerCase())??[];return e.length===0?"":e.map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join("")},xt=t=>t?t.split(/(?=[A-Z])|[\.\-\s_]/).map(e=>e.trim()).filter(e=>!!e).map(e=>p(e.toLowerCase())).join(" "):"",te=(t,e,n=/\{\{(.+?)\}\}/g)=>Array.from(t.matchAll(n)).reduce((r,s)=>r.replace(s[0],e[s[1]]),t),ee=(t,e=" ")=>{if(!t)return"";const n=e.replace(/[\W]{1}/g,"\\$&"),r=new RegExp(`^[${n}]+|[${n}]+$`,"g");return t.replace(r,"")};return u.all=kt,u.alphabetical=tt,u.assign=q,u.boil=O,u.callable=St,u.camel=Ht,u.capitalize=p,u.chain=Ct,u.clone=F,u.cluster=it,u.compose=$t,u.construct=Kt,u.counting=et,u.crush=Ut,u.dash=Vt,u.debounce=jt,u.defer=pt,u.diff=ht,u.draw=Wt,u.first=G,u.flat=ot,u.fork=L,u.get=R,u.group=Y,u.guard=At,u.intersects=lt,u.invert=Dt,u.isArray=w,u.isDate=T,u.isEmpty=X,u.isEqual=z,u.isFloat=J,u.isFunction=y,u.isInt=W,u.isNumber=h,u.isObject=k,u.isPrimitive=N,u.isPromise=j,u.isString=K,u.isSymbol=E,u.iterate=M,u.keys=v,u.last=x,u.list=C,u.listify=It,u.lowerize=Ft,u.map=yt,u.mapEntries=Zt,u.mapKeys=P,u.mapValues=Mt,u.max=st,u.memo=Tt,u.merge=ft,u.min=ut,u.objectify=B,u.omit=vt,u.parallel=bt,u.partial=Pt,u.partob=_t,u.pascal=Gt,u.pick=qt,u.proxied=Et,u.random=_,u.range=A,u.reduce=wt,u.replace=nt,u.replaceOrAppend=at,u.retry=Ot,u.select=rt,u.series=Yt,u.set=I,u.shake=Lt,u.shift=mt,u.shuffle=Jt,u.sift=gt,u.sleep=$,u.snake=Qt,u.sort=S,u.sum=V,u.template=te,u.throttle=zt,u.title=xt,u.toFloat=Bt,u.toInt=D,u.toggle=dt,u.trim=ee,u.try=m,u.tryit=m,u.uid=Xt,u.unique=ct,u.upperize=Rt,u.zip=H,u.zipToObject=Q,u}({}); +var radash=function(u){"use strict";const E=t=>!!t&&t.constructor===Symbol,w=Array.isArray,k=t=>!!t&&t.constructor===Object,N=t=>t==null||typeof t!="object"&&typeof t!="function",y=t=>!!(t&&t.constructor&&t.call&&t.apply),K=t=>typeof t=="string"||t instanceof String,W=t=>h(t)&&t%1===0,J=t=>h(t)&&t%1!==0,h=t=>{try{return Number(t)===t}catch{return!1}},T=t=>Object.prototype.toString.call(t)==="[object Date]",j=t=>!(!t||!t.then||!y(t.then)),X=t=>{if(t===!0||t===!1||t==null)return!0;if(h(t))return t===0;if(T(t))return isNaN(t.getTime());if(y(t)||E(t))return!1;const e=t.length;if(h(e))return e===0;const n=t.size;return h(n)?n===0:Object.keys(t).length===0},z=(t,e)=>{if(Object.is(t,e))return!0;if(t instanceof Date&&e instanceof Date)return t.getTime()===e.getTime();if(t instanceof RegExp&&e instanceof RegExp)return t.toString()===e.toString();if(typeof t!="object"||t===null||typeof e!="object"||e===null)return!1;const n=Reflect.ownKeys(t),r=Reflect.ownKeys(e);if(n.length!==r.length)return!1;for(let s=0;st.reduce((n,r)=>{const s=e(r);return n[s]||(n[s]=[]),n[s].push(r),n},{});function H(...t){return!t||!t.length?[]:new Array(Math.max(...t.map(({length:e})=>e))).fill([]).map((e,n)=>t.map(r=>r[n]))}function Q(t,e){if(!t||!t.length)return{};const n=y(e)?e:w(e)?(r,s)=>e[s]:(r,s)=>e;return t.reduce((r,s,i)=>(r[s]=n(s,i),r),{})}const O=(t,e)=>!t||(t.length??0)===0?null:t.reduce(e),V=(t,e)=>(t||[]).reduce((n,r)=>n+(e?e(r):r),0),G=(t,e=void 0)=>t?.length>0?t[0]:e,x=(t,e=void 0)=>t?.length>0?t[t.length-1]:e,S=(t,e,n=!1)=>{if(!t)return[];const r=(i,c)=>e(i)-e(c),s=(i,c)=>e(c)-e(i);return t.slice().sort(n===!0?s:r)},tt=(t,e,n="asc")=>{if(!t)return[];const r=(i,c)=>`${e(i)}`.localeCompare(e(c)),s=(i,c)=>`${e(c)}`.localeCompare(e(i));return t.slice().sort(n==="desc"?s:r)},et=(t,e)=>t?t.reduce((n,r)=>{const s=e(r);return n[s]=(n[s]??0)+1,n},{}):{},nt=(t,e,n)=>{if(!t)return[];if(e===void 0)return[...t];for(let r=0;rr)=>t.reduce((r,s)=>(r[e(s)]=n(s),r),{}),rt=(t,e,n)=>t?t.reduce((r,s,i)=>(n(s,i)&&r.push(e(s,i)),r),[]):[];function st(t,e){const n=e??(r=>r);return O(t,(r,s)=>n(r)>n(s)?r:s)}function ut(t,e){const n=e??(r=>r);return O(t,(r,s)=>n(r){const n=Math.ceil(t.length/e);return new Array(n).fill(null).map((r,s)=>t.slice(s*e,s*e+e))},ct=(t,e)=>{const n=t.reduce((r,s)=>{const i=e?e(s):s;return r[i]||(r[i]=s),r},{});return Object.values(n)};function*A(t,e,n=s=>s,r=1){const s=y(n)?n:()=>n,i=e?t:0,c=e??t;for(let o=i;o<=c&&(yield s(o),!(o+r>c));o+=r);}const C=(t,e,n,r)=>Array.from(A(t,e,n,r)),ot=t=>t.reduce((e,n)=>(e.push(...n),e),[]),lt=(t,e,n)=>{if(!t||!e)return!1;const r=n??(i=>i),s=e.reduce((i,c)=>(i[r(c)]=!0,i),{});return t.some(i=>s[r(i)])},L=(t,e)=>t?t.reduce((n,r)=>{const[s,i]=n;return e(r)?[[...s,r],i]:[s,[...i,r]]},[[],[]]):[[],[]],ft=(t,e,n)=>!e&&!t?[]:e?t?n?t.reduce((r,s)=>{const i=e.find(c=>n(s)===n(c));return i?r.push(i):r.push(s),r},[]):t:[]:t,at=(t,e,n)=>{if(!t&&!e)return[];if(!e)return[...t];if(!t)return[e];for(let r=0;r{if(!t&&!e)return[];if(!t)return[e];if(!e)return[...t];const s=n?(o,a)=>n(o,a)===n(e,a):o=>o===e;return t.find(s)?t.filter((o,a)=>!s(o,a)):(r?.strategy??"append")==="append"?[...t,e]:[e,...t]},gt=t=>t?.filter(e=>!!e)??[],M=(t,e,n)=>{let r=n;for(let s=1;s<=t;s++)r=e(r,s);return r},ht=(t,e,n=r=>r)=>{if(!t?.length&&!e?.length)return[];if(t?.length===void 0)return[...e];if(!e?.length)return[...t];const r=e.reduce((s,i)=>(s[n(i)]=!0,s),{});return t.filter(s=>!r[n(s)])};function mt(t,e){if(t.length===0)return t;const n=e%t.length;return n===0?t:[...t.slice(-n,t.length),...t.slice(0,-n)]}const wt=async(t,e,n)=>{const r=n!==void 0;if(!r&&t?.length<1)throw new Error("Cannot reduce empty array with no init value");const s=r?t:t.slice(1);let i=r?n:t[0];for(const[c,o]of s.entries())i=await e(i,o,c);return i},yt=async(t,e)=>{if(!t)return[];let n=[],r=0;for(const s of t){const i=await e(s,r++);n.push(i)}return n},pt=async t=>{const e=[],n=(i,c)=>e.push({fn:i,rethrow:c?.rethrow??!1}),[r,s]=await m(t)(n);for(const{fn:i,rethrow:c}of e){const[o]=await m(i)(r);if(o&&c)throw o}if(r)throw r;return s};class Z extends Error{constructor(e=[]){super();const n=e.find(r=>r.name)?.name??"";this.name=`AggregateError(${n}...)`,this.message=`AggregateError with ${e.length} errors`,this.stack=e.find(r=>r.stack)?.stack??this.stack,this.errors=e}}const bt=async(t,e,n)=>{const r=e.map((d,b)=>({index:b,item:d})),s=async d=>{const b=[];for(;;){const l=r.pop();if(!l)return d(b);const[f,g]=await m(n)(l.item);b.push({error:f,result:g,index:l.index})}},i=C(1,t).map(()=>new Promise(s)),c=await Promise.all(i),[o,a]=L(S(c.flat(),d=>d.index),d=>!!d.error);if(o.length>0)throw new Z(o.map(d=>d.error));return a.map(d=>d.result)};async function kt(t){const e=w(t)?t.map(s=>[null,s]):Object.entries(t),n=await Promise.all(e.map(([s,i])=>i.then(c=>({result:c,exc:null,key:s})).catch(c=>({result:null,exc:c,key:s})))),r=n.filter(s=>s.exc);if(r.length>0)throw new Z(r.map(s=>s.exc));return w(t)?n.map(s=>s.result):n.reduce((s,i)=>({...s,[i.key]:i.result}),{})}const Ot=async(t,e)=>{const n=t?.times??3,r=t?.delay,s=t?.backoff??null;for(const i of A(1,n)){const[c,o]=await m(e)(a=>{throw{_exited:a}});if(!c)return o;if(c._exited)throw c._exited;if(i===n)throw c;r&&await $(r),s&&await $(s(i))}},$=t=>new Promise(e=>setTimeout(e,t)),m=t=>(...e)=>{try{const n=t(...e);return j(n)?n.then(r=>[void 0,r]).catch(r=>[r,void 0]):[void 0,n]}catch(n){return[n,void 0]}},At=(t,e)=>{const n=s=>{if(e&&!e(s))throw s},r=s=>s instanceof Promise;try{const s=t();return r(s)?s.catch(n):s}catch(s){return n(s)}};function Ct(...t){return function(n){return t.reduce((r,s)=>s(r),n)}}const $t=(...t)=>t.reverse().reduce((e,n)=>n(e)),Pt=(t,...e)=>(...n)=>t(...e,...n),_t=(t,e)=>n=>t({...e,...n}),Et=t=>new Proxy({},{get:(e,n)=>t(n)}),Nt=(t,e,n,r)=>function(...i){const c=n?n(...i):JSON.stringify({args:i}),o=t[c];if(o!==void 0&&(!o.exp||o.exp>new Date().getTime()))return o.value;const a=e(...i);return t[c]={exp:r?new Date().getTime()+r:null,value:a},a},Tt=(t,e={})=>Nt({},t,e.key??null,e.ttl??null),jt=({delay:t},e)=>{let n,r=!0;const s=(...i)=>{r?(clearTimeout(n),n=setTimeout(()=>{r&&e(...i),n=void 0},t)):e(...i)};return s.isPending=()=>n!==void 0,s.cancel=()=>{r=!1},s.flush=(...i)=>e(...i),s},zt=({interval:t},e)=>{let n=!0,r;const s=(...i)=>{n&&(e(...i),n=!1,r=setTimeout(()=>{n=!0,r=void 0},t))};return s.isThrottled=()=>r!==void 0,s},St=(t,e)=>{const n=()=>{};return new Proxy(Object.assign(n,t),{get:(r,s)=>r[s],set:(r,s,i)=>(r[s]=i,!0),apply:(r,s,i)=>e(Object.assign({},r))(...i)})},Bt=(t,e)=>{const n=e===void 0?0:e;if(t==null)return n;const r=parseFloat(t);return isNaN(r)?n:r},D=(t,e)=>{const n=e===void 0?0:e;if(t==null)return n;const r=parseInt(t);return isNaN(r)?n:r},Lt=(t,e=n=>n===void 0)=>t?Object.keys(t).reduce((r,s)=>(e(t[s])||(r[s]=t[s]),r),{}):{},P=(t,e)=>Object.keys(t).reduce((r,s)=>(r[e(s,t[s])]=t[s],r),{}),Mt=(t,e)=>Object.keys(t).reduce((r,s)=>(r[s]=e(t[s],s),r),{}),Zt=(t,e)=>t?Object.entries(t).reduce((n,[r,s])=>{const[i,c]=e(r,s);return n[i]=c,n},{}):{},Dt=t=>t?Object.keys(t).reduce((n,r)=>(n[t[r]]=r,n),{}):{},Ft=t=>P(t,e=>e.toLowerCase()),It=t=>P(t,e=>e.toUpperCase()),F=t=>{if(N(t))return t;if(typeof t=="function")return t.bind({});const e=new t.constructor;return Object.getOwnPropertyNames(t).forEach(n=>{e[n]=t[n]}),e},Rt=(t,e)=>{if(!t)return[];const n=Object.entries(t);return n.length===0?[]:n.reduce((r,s)=>(r.push(e(s[0],s[1])),r),[])},qt=(t,e)=>t?e.reduce((n,r)=>(Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]),n),{}):{},vt=(t,e)=>t?!e||e.length===0?t:e.reduce((n,r)=>(delete n[r],n),{...t}):{},I=(t,e,n)=>{const r=e.split(/[\.\[\]]/g);let s=t;for(const i of r){if(s===null||s===void 0)return n;i.trim()!==""&&(s=s[i])}return s===void 0?n:s},R=(t,e,n)=>{if(!t)return{};if(!e||n===void 0)return t;const r=e.split(/[\.\[\]]/g).filter(c=>!!c.trim()),s=c=>{if(r.length>1){const o=r.shift(),a=D(r[0],null)!==null;c[o]=c[o]===void 0?a?[]:{}:c[o],s(c[o])}else c[r[0]]=n},i=F(t);return s(i),i},q=(t,e)=>!t||!e?t??e??{}:Object.entries({...t,...e}).reduce((n,[r,s])=>({...n,[r]:(()=>k(t[r])?q(t[r],s):s)()}),{}),v=t=>{if(!t)return[];const e=(n,r)=>k(n)?Object.entries(n).flatMap(([s,i])=>e(i,[...r,s])):w(n)?n.flatMap((s,i)=>e(s,[...r,`${i}`])):[r.join(".")];return e(t,[])},Ut=t=>t?B(v(t),e=>e,e=>I(t,e)):{},Kt=t=>t?Object.keys(t).reduce((e,n)=>R(e,n,t[n]),{}):{},_=(t,e)=>Math.floor(Math.random()*(e-t+1)+t),Wt=t=>{const e=t.length;if(e===0)return null;const n=_(0,e-1);return t[n]},Jt=t=>t.map(e=>({rand:Math.random(),value:e})).sort((e,n)=>e.rand-n.rand).map(e=>e.value),Xt=(t,e="")=>{const n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"+e;return M(t,r=>r+n.charAt(_(0,n.length-1)),"")},Yt=(t,e=n=>`${n}`)=>{const{indexesByKey:n,itemsByIndex:r}=t.reduce((l,f,g)=>({indexesByKey:{...l.indexesByKey,[e(f)]:g},itemsByIndex:{...l.itemsByIndex,[g]:f}}),{indexesByKey:{},itemsByIndex:{}}),s=(l,f)=>n[e(l)]n[e(l)]>n[e(f)]?l:f,c=()=>r[0],o=()=>r[t.length-1],a=(l,f)=>r[n[e(l)]+1]??f??c(),d=(l,f)=>r[n[e(l)]-1]??f??o();return{min:s,max:i,first:c,last:o,next:a,previous:d,spin:(l,f)=>{if(f===0)return l;const g=Math.abs(f),ne=g>t.length?g%t.length:g;return C(0,ne-1).reduce(U=>f>0?a(U):d(U),l)}}},p=t=>{if(!t||t.length===0)return"";const e=t.toLowerCase();return e.substring(0,1).toUpperCase()+e.substring(1,e.length)},Ht=t=>{const e=t?.replace(/([A-Z])+/g,p)?.split(/(?=[A-Z])|[\.\-\s_]/).map(n=>n.toLowerCase())??[];return e.length===0?"":e.length===1?e[0]:e.reduce((n,r)=>`${n}${r.charAt(0).toUpperCase()}${r.slice(1)}`)},Qt=(t,e)=>{const n=t?.replace(/([A-Z])+/g,p).split(/(?=[A-Z])|[\.\-\s_]/).map(s=>s.toLowerCase())??[];if(n.length===0)return"";if(n.length===1)return n[0];const r=n.reduce((s,i)=>`${s}_${i.toLowerCase()}`);return e?.splitOnNumber===!1?r:r.replace(/([A-Za-z]{1}[0-9]{1})/,s=>`${s[0]}_${s[1]}`)},Vt=t=>{const e=t?.replace(/([A-Z])+/g,p)?.split(/(?=[A-Z])|[\.\-\s_]/).map(n=>n.toLowerCase())??[];return e.length===0?"":e.length===1?e[0]:e.reduce((n,r)=>`${n}-${r.toLowerCase()}`)},Gt=t=>{const e=t?.split(/[\.\-\s_]/).map(n=>n.toLowerCase())??[];return e.length===0?"":e.map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join("")},xt=t=>t?t.split(/(?=[A-Z])|[\.\-\s_]/).map(e=>e.trim()).filter(e=>!!e).map(e=>p(e.toLowerCase())).join(" "):"",te=(t,e,n=/\{\{(.+?)\}\}/g)=>Array.from(t.matchAll(n)).reduce((r,s)=>r.replace(s[0],e[s[1]]),t),ee=(t,e=" ")=>{if(!t)return"";const n=e.replace(/[\W]{1}/g,"\\$&"),r=new RegExp(`^[${n}]+|[${n}]+$`,"g");return t.replace(r,"")};return u.all=kt,u.alphabetical=tt,u.assign=q,u.boil=O,u.callable=St,u.camel=Ht,u.capitalize=p,u.chain=Ct,u.clone=F,u.cluster=it,u.compose=$t,u.construct=Kt,u.counting=et,u.crush=Ut,u.dash=Vt,u.debounce=jt,u.defer=pt,u.diff=ht,u.draw=Wt,u.first=G,u.flat=ot,u.fork=L,u.get=I,u.group=Y,u.guard=At,u.intersects=lt,u.invert=Dt,u.isArray=w,u.isDate=T,u.isEmpty=X,u.isEqual=z,u.isFloat=J,u.isFunction=y,u.isInt=W,u.isNumber=h,u.isObject=k,u.isPrimitive=N,u.isPromise=j,u.isString=K,u.isSymbol=E,u.iterate=M,u.keys=v,u.last=x,u.list=C,u.listify=Rt,u.lowerize=Ft,u.map=yt,u.mapEntries=Zt,u.mapKeys=P,u.mapValues=Mt,u.max=st,u.memo=Tt,u.merge=ft,u.min=ut,u.objectify=B,u.omit=vt,u.parallel=bt,u.partial=Pt,u.partob=_t,u.pascal=Gt,u.pick=qt,u.proxied=Et,u.random=_,u.range=A,u.reduce=wt,u.replace=nt,u.replaceOrAppend=at,u.retry=Ot,u.select=rt,u.series=Yt,u.set=R,u.shake=Lt,u.shift=mt,u.shuffle=Jt,u.sift=gt,u.sleep=$,u.snake=Qt,u.sort=S,u.sum=V,u.template=te,u.throttle=zt,u.title=xt,u.toFloat=Bt,u.toInt=D,u.toggle=dt,u.trim=ee,u.try=m,u.tryit=m,u.uid=Xt,u.unique=ct,u.upperize=It,u.zip=H,u.zipToObject=Q,u}({}); \ No newline at end of file diff --git a/docs/curry/chain.mdx b/docs/curry/chain.mdx index 8106f178..51565dc7 100644 --- a/docs/curry/chain.mdx +++ b/docs/curry/chain.mdx @@ -7,15 +7,42 @@ description: Create a chain of function to run in order ## Basic usage Chaining functions will cause them to execute one after another, passing the output from each function as the input to the next, returning the final output at the end of the chain. +```ts +import { chain } from 'radash' + +const add = (y: number) => (x: number) => x + y +const mult = (y: number) => (x: number) => x * y +const addFive = add(5) +const double = mult(2) + +const chained = chain(addFive, double) + +chained(0) // => 10 +chained(7) // => 24 +``` +### More example ```ts import { chain } from 'radash' -const genesis = () => 0 -const addFive = (num: number) => num + 5 -const twoX = (num: number) => num * 2 +type User = { id: number; name: string } +const users: User[] = [ + { id: 1, name: 'John Doe' }, + { id: 2, name: 'John Smith' }, + { id: 3, name: 'John Wick' } +] +function getName(item: T) { + return item.name; +} +function upperCase(text: string): Uppercase { + return text.toUpperCase() as Uppercase; +} -const chained = chain(genesis, addFive, twoX) +const getUpperName = chain>(getName, upperCase) +// ^ Use chain function here -chained() // => 10 +getUpperName(users[0]) // => 'JOHN DOE' +users.map((user) => getUpperName(user)) // => ['JOHN DOE', 'JOHN SMITH', 'JOHN WICK'] +users.map(getUpperName) // => ['JOHN DOE', 'JOHN SMITH', 'JOHN WICK'] +// ^ use chained function as a Point-free ``` diff --git a/src/curry.ts b/src/curry.ts index 7bb091be..4bd57846 100644 --- a/src/curry.ts +++ b/src/curry.ts @@ -1,12 +1,55 @@ +export type UnaryFunc = (arg: T) => R export type Func = ( ...args: TArgs[] ) => KReturn -export const chain = - (...funcs: Func[]) => - (...args: any[]) => { - return funcs.slice(1).reduce((acc, fn) => fn(acc), funcs[0](...args)) +export function chain( + fn1: UnaryFunc, + fn2: UnaryFunc +): UnaryFunc +export function chain( + fn1: UnaryFunc, + fn2: UnaryFunc, + fn3: UnaryFunc +): UnaryFunc +export function chain( + fn1: UnaryFunc, + fn2: UnaryFunc, + fn3: UnaryFunc, + fn4: UnaryFunc +): UnaryFunc +export function chain( + fn1: UnaryFunc, + fn2: UnaryFunc, + fn3: UnaryFunc, + fn4: UnaryFunc, + fn5: UnaryFunc +): UnaryFunc +export function chain( + fn1: UnaryFunc, + fn2: UnaryFunc, + fn3: UnaryFunc, + fn4: UnaryFunc, + fn5: UnaryFunc, + fn6: UnaryFunc +): UnaryFunc +export function chain( + fn1: UnaryFunc, + fn2: UnaryFunc, + fn3: UnaryFunc, + fn4: UnaryFunc, + fn5: UnaryFunc, + fn6: UnaryFunc, + fn7: UnaryFunc +): UnaryFunc +export function chain( + ...fns: ((arg: any) => any)[] +): UnaryFunc +export function chain(...funcs: Func[]): Func { + return function forInitialArg(initialArg: Parameters[0]) { + return funcs.reduce((acc, fn) => fn(acc), initialArg) } +} export const compose = (...funcs: Func[]) => { return funcs.reverse().reduce((acc, fn) => fn(acc)) diff --git a/src/tests/curry.test.ts b/src/tests/curry.test.ts index cf63aa37..fdbd446d 100644 --- a/src/tests/curry.test.ts +++ b/src/tests/curry.test.ts @@ -94,9 +94,54 @@ describe('curry module', () => { const addFive = (num: number) => num + 5 const twoX = (num: number) => num * 2 const func = _.chain(genesis, addFive, twoX) - const result = func() + const result = func(0) assert.equal(result, 10) }) + + test('calls add(1), then addFive, then twoX functions by 1', () => { + const add = (y: number) => (x: number) => x + y + const addFive = add(5) + const twoX = (num: number) => num * 2 + const func = _.chain(add(1), addFive, twoX) + const result = func(1) + assert.equal(result, 14) + }) + + test('calls add(2), then addFive, then twoX, then repeatX functions by 1', () => { + const add = (y: number) => (x: number) => x + y + const addFive = add(5) + const twoX = (num: number) => num * 2 + const repeatX = (num: number) => 'X'.repeat(num) + const func = _.chain(add(2), addFive, twoX, repeatX) + const result = func(1) + assert.equal(result, 'XXXXXXXXXXXXXXXX') + }) + + test('calls addFive, then add(2), then twoX, then repeatX functions by 1', () => { + const add = (y: number) => (x: number) => x + y + const addFive = add(5) + const twoX = (num: number) => num * 2 + const repeatX = (num: number) => 'X'.repeat(num) + const func = _.chain(addFive, add(2), twoX, repeatX) + const result = func(1) + assert.equal(result, 'XXXXXXXXXXXXXXXX') + }) + + test('calls getName, then upperCase functions as a mapper for User[]', () => { + type User = { id: number; name: string } + const users: User[] = [ + { id: 1, name: 'John Doe' }, + { id: 2, name: 'John Smith' }, + { id: 3, name: 'John Wick' } + ] + const getName = (item: T) => item.name + const upperCase: (x: string) => Uppercase = (text: string) => + text.toUpperCase() as Uppercase + + const getUpperName = _.chain>(getName, upperCase) + const result = users.map(getUpperName) + assert.deepEqual(result, ['JOHN DOE', 'JOHN SMITH', 'JOHN WICK']) + }) }) describe('proxied function', () => {