{"id":7865,"date":"2016-11-11T11:12:03","date_gmt":"2016-11-11T09:12:03","guid":{"rendered":"https:\/\/www.synthesis.co.za\/?p=832"},"modified":"2016-11-11T11:12:03","modified_gmt":"2016-11-11T09:12:03","slug":"functional-fun-typescript-generics","status":"publish","type":"post","link":"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/","title":{"rendered":"Functional fun with TypeScript Generics"},"content":{"rendered":"<link rel=\"stylesheet\" href=\"https:\/\/stackedit.io\/res-min\/themes\/base.css\" \/>\n<script type=\"text\/javascript\" src=\"https:\/\/cdn.mathjax.org\/mathjax\/latest\/MathJax.js?config=TeX-AMS_HTML\"><\/script><\/p>\n<p>This weekend I decided to try my hand at TypeScript. The goal I had was to implement a <code>curry<\/code> function which can curry other functions with variable length arguments. Although this is a trivial exercise in JavaScript, i was interested in what it would take to implement a version in TypeScript which would be able to check the types of arguments of a curried function at compile time.<\/p>\n<h2 id=\"background\">Background<\/h2>\n<p>What does it mean to curry a function? <br \/>\nBasically,  if you have a function with the following signature (A function signature is a way of defining what a function \u2018looks\u2019 like. You can think of a function signature as a describing a function\u2019s type. ):<\/p>\n<pre class=\"prettyprint\"><code class=\"language-ts hljs actionscript\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">foo<\/span><span class=\"hljs-params\">(a: string, b: string, c: number)<\/span><span class=\"hljs-type\">:string<\/span>;<\/span><\/code><\/pre>\n<p>This signature tells us that our function, <code>foo<\/code> takes 2 arguments of type <code>string<\/code>  and 1 argument of type <code>number<\/code>, and returns something with type <code>string<\/code>.<\/p>\n<p>An example of a call to function <code>foo<\/code> might look like this:<\/p>\n<pre class=\"prettyprint\"><code class=\" hljs scss\"><span class=\"hljs-function\">foo(<span class=\"hljs-string\">\"bar\"<\/span>,<span class=\"hljs-string\">\"baz\"<\/span>,<span class=\"hljs-number\">123<\/span>)<\/span>;<\/code><\/pre>\n<p>A curried version of the function <code>foo<\/code>, <code>Cfoo<\/code>, can be called as a chain of functions:<\/p>\n<pre class=\"prettyprint\"><code class=\" hljs bash\">Cfoo(<span class=\"hljs-string\">\"bar\"<\/span>)(<span class=\"hljs-string\">\"baz\"<\/span>)(<span class=\"hljs-number\">123<\/span>);<\/code><\/pre>\n<p>i.e. A curried function returns function which takes one argument (or more), which will return a partially applied function which takes one argument(or more), and so-on, until the last function is called which in turn will call the underlying function (like we did to <code>foo<\/code>, in the above example).<\/p>\n<h2 id=\"so-why-would-you-want-to-curry-anything\">So, why would you want to curry anything?<\/h2>\n<p>It\u2019s a pattern which encapsulates state. Let me give an example: <br \/>\nLet\u2019s say you have a dbQuery API function with the following signature<\/p>\n<pre class=\"prettyprint\"><code class=\"language-ts hljs actionscript\"><span class=\"hljs-comment\">\/\/ fake implementation of the API we have to work with...<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">dbQuery<\/span><span class=\"hljs-params\">(connStr:string,conf:Object,query:string)<\/span><span class=\"hljs-type\">:string<\/span>;<\/span><\/code><\/pre>\n<p>To avoid having to write out the connection string and pass a config object around every time you want to make a query: you could take the Object-Orientated approach (where you need to implement a class which maintains the connection string and db config and which then exposes a query method, etc.) or, assuming you have a implementation of <code>curryN<\/code>, by simply doing this in an app\u2019s boot-up code:<\/p>\n<pre class=\"prettyprint\"><code class=\"language-js hljs \"><span class=\"hljs-comment\">\/\/ please don't ever hard-code auth details! This is an example only.<\/span>\n<span class=\"hljs-keyword\">let<\/span> query = curryN(dbQuery,<span class=\"hljs-number\">3<\/span>)(<span class=\"hljs-string\">\"foo\/\/bar\/baz\"<\/span>,{ usr: <span class=\"hljs-string\">'foo'<\/span>, pass: <span class=\"hljs-string\">'bar'<\/span>});<\/code><\/pre>\n<p>This reusable function <code>query<\/code> can be passed to the rest of your app.  <code>query<\/code>, will now implicitly have the signature:<code>query(queryStr:string):string<\/code> (since the first 2 parameters were already partially applied immediately after calling the <code>curryN<\/code> function). Note that the connection string and configObj are no longer needed: developers using this function would just focus on the query, and it is called just as you would a regular function:<\/p>\n<pre class=\"prettyprint\"><code class=\"language-js hljs \"><span class=\"hljs-comment\">\/\/ don't ever do this!<\/span>\nquery(<span class=\"hljs-string\">\"DROP * FROM TABLES;\"<\/span>);<\/code><\/pre>\n<p>The above code is doing what the following equivalent, not very well written, TypeScript OO code would do:<\/p>\n<pre class=\"prettyprint\"><code class=\"language-ts hljs axapta\"><span class=\"hljs-comment\">\/\/ because other api's also need this...<\/span>\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">dbConnection<\/span> {<\/span>\n    connStr:string;\n    conf:Object;<span class=\"hljs-comment\">\/\/ Note I'm omitting this class definition for brevity...<\/span>\n    constructor(connStr:string,conf:Object){\n        <span class=\"hljs-keyword\">this<\/span>.connStr = connStr;\n        <span class=\"hljs-keyword\">this<\/span>.conf = conf;\n    }\n}\n\n<span class=\"hljs-comment\">\/\/ because Bjarne Stroustrup told me it's cool to inherit<\/span>\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">query<\/span> <span class=\"hljs-inheritance\"><span class=\"hljs-keyword\">extends<\/span><\/span> <span class=\"hljs-title\">dbConnection<\/span> {<\/span>\n    constructor(connStr:string,conf:Object){\n        <span class=\"hljs-keyword\">super<\/span>(connStr,conf);\n    }   \n    <span class=\"hljs-keyword\">public<\/span> query(query:string){\n        <span class=\"hljs-keyword\">return<\/span> dbQuery(<span class=\"hljs-keyword\">this<\/span>.connStr,<span class=\"hljs-keyword\">this<\/span>.conf,query);\n    }\n}\n\n<span class=\"hljs-comment\">\/* in init code somewhere *\/<\/span>\nlet query = <span class=\"hljs-keyword\">new<\/span> DbQuery(<span class=\"hljs-string\">\"foo\/\/bar\/baz\"<\/span>,{ usr: <span class=\"hljs-string\">'foo'<\/span>, pass: <span class=\"hljs-string\">'bar'<\/span>});\n<span class=\"hljs-comment\">\/\/ please don't ever hard-code auth details! This is an example only. You would assume that in 'real' code, the connStr and conf object would be configurable somewhere in a file never seen by git...<\/span>\n\n<span class=\"hljs-comment\">\/\/don't do this..<\/span>\nquery.query(<span class=\"hljs-string\">\"DROP * FROM TABLES;\"<\/span>);\n<\/code><\/pre>\n<p>In the following section you\u2019ll see that a JavaScript implementation of curryN is more terse than the OO plumbing in the TypeScript code above.<\/p>\n<p>Keep in mind that the above OO code will do essentially what the one-liner did when we just curried the API function.<\/p>\n<h2 id=\"currying-in-javascript\">Currying in JavaScript<\/h2>\n<p>Before we go on to the TypeScript implementation, let\u2019s see how things work in plain old JavaScript.<\/p>\n<h3 id=\"general-null-terminated-curry-implementation\">General null terminated <code>curry<\/code> implementation<\/h3>\n<p>Below is a generic JavaScript implementation of a variable-length-argument, null terminated <code>curry<\/code> function (some type of termination is required for variable-length-argument curried functions). <\/p>\n<pre class=\"prettyprint\"><code class=\"language-js hljs \"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">curry<\/span><span class=\"hljs-params\">(f)<\/span> {<\/span>\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">()<\/span> {<\/span>\n        <span class=\"hljs-keyword\">var<\/span> args = <span class=\"hljs-built_in\">Array<\/span>.prototype.slice.call(<span class=\"hljs-built_in\">arguments<\/span>);\n        <span class=\"hljs-keyword\">if<\/span> (args.length)\n            <span class=\"hljs-keyword\">return<\/span> curry(f.bind.apply(f, [<span class=\"hljs-literal\">undefined<\/span>].concat(args)));\n        <span class=\"hljs-keyword\">return<\/span> f();\n    };\n}<\/code><\/pre>\n<h3 id=\"general-curryn-implementation\">General <code>curryN<\/code> implementation<\/h3>\n<p>For currying known argument-length functions:<\/p>\n<pre class=\"prettyprint\"><code class=\"language-js hljs \"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">curryN<\/span><span class=\"hljs-params\">(f,n)<\/span> {<\/span>\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">()<\/span> {<\/span>\n        <span class=\"hljs-keyword\">var<\/span> args = <span class=\"hljs-built_in\">Array<\/span>.prototype.slice.call(<span class=\"hljs-built_in\">arguments<\/span>);\n        <span class=\"hljs-keyword\">if<\/span> (args.length&lt;n){\n            <span class=\"hljs-keyword\">return<\/span> curryN(f.bind.apply(f, [<span class=\"hljs-literal\">undefined<\/span>].concat(args)),n-args.length);\n        }\n        <span class=\"hljs-keyword\">return<\/span> f.apply(<span class=\"hljs-literal\">undefined<\/span>,args);\n    };\n}<\/code><\/pre>\n<p>We are employing three JavaScript tricks in the above two functions, <code>curry<\/code>, and <code>curryN<\/code>: <\/p>\n<ol>\n<li>The JavaScript way of converting an <code>arguments<\/code> array into a \u2018real\u2019 array (<code>var args = Array.prototype.slice.call(arguments);<\/code>) is necessary to later use the <code>Array.concat<\/code> method. <\/li>\n<li>The JavaScript <code>bind<\/code> function performs a partial application of a function (exactly what we want for currying). We are recursively calling the curry function to return another function with the bound function until we run over the argument limit or get null terminated at which point we call the bound function.<\/li>\n<li>We are also calling <code>apply<\/code> as a means to feed in an array of arguments as a list of arguments into the invoking function.  <\/li>\n<li>Eg.: If <code>args<\/code> was <code>[\"Foo\",1]<\/code>, then <code>f.apply(undefined,args);<\/code> invokes <code>f<\/code>, as if it was written as <code>f(\"Foo\",1);<\/code><\/li>\n<\/ol>\n<blockquote>\n<p><strong>Note<\/strong>: Because JavaScript does not check function signatures and since superfluous arguments are ignored, the above implementation will work with <strong><em>any*<\/em><\/strong> JavaScript function as input (even other curried functions!).<\/p>\n<blockquote>\n<p>*Not including native functions, like console.log\u2026 you have to wrap those around a variable-argument function yourself\u2026<\/p>\n<\/blockquote>\n<p><strong>Note in <code>curryN<\/code>:<\/strong>  <em>less than<\/em> is used in the check <code>if(args.length&lt;n)<\/code>, to account for JavaScript not caring about superfluous arguments\u2026 otherwise it would be <code>if(args.length==n)<\/code><\/p>\n<\/blockquote>\n<p>The above implementations were done rather quickly since I have a familiarity with the listed tricks: a clear vindication of JavaScript\u2019s advertised ability to do fast prototyping and a win for dynamic typing. ( If you\u2019ve spent years learning the tricks, that is. )<\/p>\n<p>To wrap up the JavaScript implementation: <br \/>\nExample usage of the <code>curry<\/code> function with the example function <code>foo<\/code> from the previous section:<\/p>\n<pre class=\"prettyprint\"><code class=\" hljs cs\"><span class=\"hljs-keyword\">var<\/span> Cfoo = curry(foo);\nCfoo(<span class=\"hljs-string\">\"bar\"<\/span>)(<span class=\"hljs-string\">\"baz\"<\/span>)(<span class=\"hljs-number\">123<\/span>)(); <span class=\"hljs-comment\">\/\/ (null terminated)<\/span>\nCfoo(<span class=\"hljs-string\">\"bar\"<\/span>)(<span class=\"hljs-string\">\"baz\"<\/span>,<span class=\"hljs-number\">123<\/span>)(); <span class=\"hljs-comment\">\/\/ equivalent behaviour to first call<\/span>\nCfoo(<span class=\"hljs-string\">\"bar\"<\/span>,<span class=\"hljs-string\">\"baz\"<\/span>)(<span class=\"hljs-number\">123<\/span>)(); <span class=\"hljs-comment\">\/\/ equivalent behaviour to first call<\/span><\/code><\/pre>\n<p>Example usage of the <code>curryN<\/code> function with the example function <code>foo<\/code> from the previous section:<\/p>\n<pre class=\"prettyprint\"><code class=\" hljs cs\"><span class=\"hljs-keyword\">var<\/span> Cfoo = curryN(foo,<span class=\"hljs-number\">3<\/span>);\nCfoo(<span class=\"hljs-string\">\"bar\"<\/span>)(<span class=\"hljs-string\">\"baz\"<\/span>)(<span class=\"hljs-number\">123<\/span>); <span class=\"hljs-comment\">\/\/ (curryN of foo)<\/span>\nCfoo(<span class=\"hljs-string\">\"bar\"<\/span>)(<span class=\"hljs-string\">\"baz\"<\/span>,<span class=\"hljs-number\">123<\/span>); <span class=\"hljs-comment\">\/\/ equivalent behaviour to first call<\/span>\nCfoo(<span class=\"hljs-string\">\"bar\"<\/span>,<span class=\"hljs-string\">\"baz\"<\/span>)(<span class=\"hljs-number\">123<\/span>); <span class=\"hljs-comment\">\/\/ equivalent behaviour to first call<\/span><\/code><\/pre>\n<p>The terseness and elegance of JavaScript is due to its untyped dynamic nature. Unfortunately this terseness and elegance also happens to infuriate those who want large-scale structure and mature tooling.<\/p>\n<p>So: can we achieve at least the functional terseness but still have type information preserved?<\/p>\n<h2 id=\"currying-in-typescript\">Currying in TypeScript<\/h2>\n<h3 id=\"but-why\">But why?!<\/h3>\n<p>What is the advantage of doing the same thing in TypeScript?<\/p>\n<p>Our one-liner <code>query<\/code> function we produced earlier from <code>curryN()<\/code> would be useless to a developer who didn\u2019t write it and had to use it. <\/p>\n<ul>\n<li><em>Imagine:<\/em> \u201c<code>query<\/code>? Is this a URL query string or a database query object? I\u2019ll have to see where it gets imported, look up that file (Since a jump-to-source isn\u2019t available because there are 2 million definitions in the project of the string <code>query<\/code>, grrr), and read the code\u2026 oh, its a data query function! \u2026ok, now I can ignore it, because I was tasked to do something with the URL query string. F.M.L.\u201d<\/li>\n<\/ul>\n<p>Consider the nature of a truly dynamic language and how difficult it must be to produce any sort of decent <em>auto-complete<\/em> not driven off of some extra source of meta-data (like a YAML definition file or jsDocs you have to maintain separately.)<\/p>\n<p>The tool-able OO plumbing code starts to look more inviting when we consider having to maintain a separate meta-data source just to convey the intent of what we\u2019ve already implemented. <\/p>\n<p>Can we can still go the functional route, and retain its benefits while getting the added benefit of conveying intent in type definitions? Might it still require less plumbing to get <em>auto-complete<\/em> on a curried function than going the OO route? <\/p>\n<p><em>Answer: Well yeah, kinda, in one particular case\u2026<\/em><\/p>\n<h3 id=\"making-it-work\">Making it work<\/h3>\n<p>The problem with using the JavaScript <code>curry<\/code> function implemented above in TypeScript is that any <a href=\"http:\/\/www.typescriptlang.org\/docs\/handbook\/basic-types.html\">type information<\/a> from the <a href=\"http:\/\/www.typescriptlang.org\/docs\/handbook\/functions.html\">function<\/a> being curried will be lost in the returned curried function. Can we overcome this limitation?<\/p>\n<blockquote>\n<p>Note: You can use the <a href=\"http:\/\/www.typescriptlang.org\/play\/\">TypeScript Playground<\/a> to follow along.<\/p>\n<\/blockquote>\n<p>One case immediately presents itself\u2026 functions which take a variable list of arguments of the same type, and return a single result of the same type. These classes of functions represent a large set of aggregate functions.  <br \/>\nEg.<\/p>\n<pre class=\"prettyprint\"><code class=\"language-js hljs \">concatStr();<span class=\"hljs-comment\">\/\/'';<\/span>\nconcatStr(<span class=\"hljs-string\">'bar'<\/span>,<span class=\"hljs-string\">'baz'<\/span>);<span class=\"hljs-comment\">\/\/'barbaz';<\/span>\nconcatStr(<span class=\"hljs-string\">'bar'<\/span>,<span class=\"hljs-string\">'baz'<\/span>,<span class=\"hljs-string\">'boo'<\/span>,<span class=\"hljs-string\">'baa'<\/span>);<span class=\"hljs-comment\">\/\/'barbazboobaa';<\/span>\nbar(someObj1);<span class=\"hljs-comment\">\/\/someNewObj;<\/span>\nbar(someObj1,someObj2,someObj3);<span class=\"hljs-comment\">\/\/someNewObj;<\/span><\/code><\/pre>\n<p>They have a common signature which can be represented in a TypeScript function <a href=\"http:\/\/www.typescriptlang.org\/docs\/handbook\/interfaces.html\">interface<\/a> as follows:<\/p>\n<pre class=\"prettyprint\"><code class=\"language-ts hljs css\"><span class=\"hljs-tag\">interface<\/span> <span class=\"hljs-tag\">aggregateFn<\/span>&lt;<span class=\"hljs-tag\">T<\/span>&gt; <span class=\"hljs-rules\">{\n    <span class=\"hljs-rule\">(<span class=\"hljs-attribute\">...args<\/span>:<span class=\"hljs-value\"> T[]): T<\/span><\/span>;\n<span class=\"hljs-rule\">}<\/span><\/span><\/code><\/pre>\n<p>This is what a function interface looks like in TypeScript. You can think of a function interface as a type definition for a set of function signatures. The <code>...<\/code> is called the \u201cspread\u201d operator and in this context it is a way you can refer to variable arguments in TypeScript as a typed array.<\/p>\n<p>The <a href=\"http:\/\/www.typescriptlang.org\/docs\/handbook\/generics.html\">generics<\/a> notation <code>&lt;T&gt;<\/code> is used to denote that the argument array\u2019s content\u2019s type and the return type are the same. You can think of a generic type as type-placeholder statement. We are keeping it simple here and sticking to one generic type.<\/p>\n<p>A curried version of this class of function interface would have to be equivalent, except that it would also need to optionally return its\u2019 own function interface:<\/p>\n<pre class=\"prettyprint\"><code class=\"language-ts hljs php\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">curryFn<\/span>&lt;<span class=\"hljs-title\">T<\/span>&gt; <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">aggregateFn<\/span>&lt;<span class=\"hljs-title\">T<\/span>&gt; {<\/span>\n    (...args: T[]): curryFn&lt;T&gt;;\n}<\/code><\/pre>\n<blockquote>\n<p><strong>Note<\/strong>: Here you can see how TypeScript can deal with the <code>extends<\/code> keyword for function interfaces &#8211; meaning that the extended function interface inherits the characteristics of the interface it is extended from. For <code>curryFn&lt;T&gt;<\/code>, the \u2018compounded\u2019 function signature set would now basically look like this: <br \/>\n  <code>(...args: any[]): curryFn&lt;any&gt; | any;<\/code> <br \/>\n  &#8211; The <code>|<\/code> means \u2018or\u2019. <br \/>\n  You can also see here how the compiler understands self-referential interfaces. <\/p>\n<\/blockquote>\n<p>Finally, we have the pieces we need to implement our special class of typed <code>curry<\/code>:<\/p>\n<pre class=\"prettyprint\"><code class=\"language-ts hljs javascript\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">curry<\/span>&lt;<span class=\"hljs-title\">T<\/span>&gt;<span class=\"hljs-params\">(f: aggregateFn&lt;T&gt;)<\/span>: <span class=\"hljs-title\">curryFn<\/span>&lt;<span class=\"hljs-title\">T<\/span>&gt; {<\/span>\n    <span class=\"hljs-keyword\">return<\/span> (...args: any[]): curryFn&lt;any&gt; | any =&gt; {\n        <span class=\"hljs-keyword\">if<\/span> (args.length)\n            <span class=\"hljs-keyword\">return<\/span> curry(f.bind.apply(f,[<span class=\"hljs-literal\">undefined<\/span>].concat(args)));\n        <span class=\"hljs-keyword\">return<\/span> f();\n    }\n}<\/code><\/pre>\n<p>Looks pretty much the same as before &#8211; good thing, because you should understand most of it by now\u2026 but let\u2019s examine the new type-related syntax\u2026 <br \/>\nIn the function signature of the returned function: <br \/>\n<code>(...args: any[]): curryFn&lt;any&gt; | any<\/code> <br \/>\nThe use of the <code>any<\/code> keyword is bound by the return type in the function signature of the enclosing function: <br \/>\n<code>function curry&lt;T&gt;(f: aggregateFn&lt;T&gt;): curryFn&lt;T&gt;<\/code> <br \/>\nwhich in this case is <code>curryFn&lt;T&gt;<\/code>.  <br \/>\nTherefore, using  the <code>curry<\/code> function on a variable-argument length function should retain type information for the returned function, and all subsequent functions returned from those functions. This gives the TypeScript compiler enough information to determine if you are making type errors in chained functions, and subsequently makes your IDE more intelligent.<\/p>\n<p>To test our new typed curry, let\u2019s employ a typed test function:<\/p>\n<pre class=\"prettyprint\"><code class=\" hljs actionscript\"><span class=\"hljs-comment\">\/*\n    test function, just adds a list of numbers.\n    @params : variable list of numbers.\n    @returns: the numbers added.\n*\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">addNumbers<\/span><span class=\"hljs-params\">(<span class=\"hljs-rest_arg\">...args<\/span>: number[])<\/span><span class=\"hljs-type\">: number<\/span> {<\/span>\n    <span class=\"hljs-keyword\">return<\/span> args.reduce((acc, itm) =&gt; acc += itm, <span class=\"hljs-number\">0<\/span>)\n}<\/code><\/pre>\n<p>To make a curried version is as simple as:<\/p>\n<pre class=\"prettyprint\"><code class=\" hljs bash\"><span class=\"hljs-built_in\">let<\/span> curriedAdd = curry(addNumbers);<\/code><\/pre>\n<blockquote>\n<p><strong>Note<\/strong>: The types are inferred. <\/p>\n<\/blockquote>\n<p>Now, when we type the following incomplete statement into a TypeScript IDE:<\/p>\n<pre class=\"prettyprint\"><code class=\" hljs erlang\"><span class=\"hljs-function\"><span class=\"hljs-title\">curriedAdd<\/span><span class=\"hljs-params\">(<span class=\"hljs-number\">1<\/span>)<\/span><span class=\"hljs-params\">(<span class=\"hljs-number\">2<\/span>)<\/span><span class=\"hljs-params\">(<span class=\"hljs-number\">3<\/span>)<\/span><span class=\"hljs-params\">(<span class=\"hljs-number\">4<\/span>)<\/span><span class=\"hljs-params\">(<span class=\"hljs-number\">5<\/span>)<\/span><span class=\"hljs-params\">(<\/span><\/span><\/code><\/pre>\n<p>The <em>auto-complete<\/em> should kick in and let you know that you\u2019re supposed to add numbers only <code>(...args: number[])<\/code> . Maybe not helpful in this example, but very helpful if a more complex type of object was required at each call.<\/p>\n<h2 id=\"were-not-done\">We\u2019re not done<\/h2>\n<p>I leave it as an exercise to the reader to implement <code>curryN&lt;T&gt;<\/code> in TypeScript. <br \/>\n<em>(Hint: I\u2019ve done most of the work for you)<\/em><\/p>\n<p>I have only presented the TypeScript <code>curry<\/code> solution for one set of functions. <\/p>\n<p>Consider functions with this signature: <br \/>\n<code>(a:fooObjType,b:any,c:barObjType,d:string,e:number,...args:any[]):bazObjType<\/code> <br \/>\nThe generic interface would have to look something like:<\/p>\n<pre class=\"prettyprint\"><code class=\" hljs css\"><span class=\"hljs-tag\">interface<\/span> <span class=\"hljs-tag\">someFn<\/span>&lt;<span class=\"hljs-tag\">T1<\/span>,<span class=\"hljs-tag\">T2<\/span>,<span class=\"hljs-tag\">T3<\/span>,<span class=\"hljs-tag\">T4<\/span>,<span class=\"hljs-tag\">T5<\/span>,<span class=\"hljs-tag\">R<\/span>&gt;<span class=\"hljs-rules\">{\n    <span class=\"hljs-rule\">(<span class=\"hljs-attribute\">a<\/span>:<span class=\"hljs-value\">T1,b?:T2,c?:T3,d?:T4,e?:T5,...args:any[]):R<\/span><\/span>;\n<span class=\"hljs-rule\">}<\/span><\/span><\/code><\/pre>\n<p>Now start thinking of how you would implement a generalised curry of that\u2026 Yikes! <\/p>\n<p>It becomes clear that for the dbQuery example before, even with 3 parameters, it makes more sense to just use a closed function which is made-for-purpose. <\/p>\n<pre class=\"prettyprint\"><code class=\"language-ts hljs coffeescript\">\/*\n  <span class=\"hljs-reserved\">function<\/span> <span class=\"hljs-attribute\">myQuery<\/span>: queries the DB.\n    <span class=\"hljs-property\">@param<\/span> <span class=\"hljs-attribute\">query<\/span>: The db Query to run.\n    <span class=\"hljs-property\">@returns<\/span>: Db Query Result.\n*\/\n<span class=\"hljs-reserved\">let<\/span> <span class=\"hljs-function\"><span class=\"hljs-title\">myQuery<\/span> = <span class=\"hljs-params\">((connStr: string, conf: Object): (query: string) =&gt; string =&gt; {\n    <span class=\"hljs-keyword\">return<\/span> (query) =&gt; dbQuery(connStr, conf, query) ;\n})(<span class=\"hljs-string\">\"foo\/\/bar\/baz\"<\/span>, { usr: <span class=\"hljs-string\">'foo'<\/span>, pass: <span class=\"hljs-string\">'bar'<\/span> })<\/span>\n<\/span><\/code><\/pre>\n<blockquote>\n<p><strong>Note<\/strong>: The return type <code>(query: string) =&gt; string<\/code> requires <code>=&gt;<\/code> in a anonymous definition. <\/p>\n<\/blockquote>\n<p>Now a 3-liner with no fancy-pants generics, not exactly worthy of much academic notice, but does the same job of encapsulating data and producing a reusable object, which happens to also be a function. Self-documenting and type-information-preserving. It is good to know that TypeScript allows us to choose the paradigm we feel is most suited for the job at hand.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>Even though it was initially painful to approach TypeScript from a functional perspective, it soon became clear that the current incarnation of the TypeScript compiler (1.8 as of writing) is capable of handling the functional paradigm in a type-safe manner. I\u2019m confident that we can port current solutions at our company that benefit from JavaScript\u2019s functional capabilities to TypeScript. The exercise would be worth the pain for the tooling benefits, boosted collaborative efforts and improved maintainability.\n<\/p>\n<p>By: Jaco Pretorius, <a href=\"https:\/\/www.linkedin.com\/company\/synthesis-software-technologies-pty-ltd\"> Synthesis Software Technologies<\/a><\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>This weekend I decided to try my hand at TypeScript. The goal I had was to implement a curry function which can curry other functions with variable length arguments. Although this is a trivial exercise in JavaScript, i was interested in what it would take to implement a version in TypeScript which would be able [&hellip;]<\/p>\n","protected":false},"author":5,"featured_media":836,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"episode_type":"","audio_file":"","cover_image":"","cover_image_id":"","duration":"","filesize":"","filesize_raw":"","date_recorded":"","explicit":"","block":"","itunes_episode_number":"","itunes_title":"","itunes_season_number":"","itunes_episode_type":"","footnotes":""},"categories":[36],"tags":[],"ptype":[12],"sectors":[],"class_list":["post-7865","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news-room","ptype-news"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.0 (Yoast SEO v27.0) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Functional fun with TypeScript Generics - Synthesis<\/title>\n<meta name=\"description\" content=\"Read: &#039;Functional fun with TypeScript Generics&#039; and more on the Synthesis blog for insights on the latest in the Tech and Software development industry.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Functional fun with TypeScript Generics\" \/>\n<meta property=\"og:description\" content=\"Read: &#039;Functional fun with TypeScript Generics&#039; and more on the Synthesis blog for insights on the latest in the Tech and Software development industry.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/\" \/>\n<meta property=\"og:site_name\" content=\"Synthesis\" \/>\n<meta property=\"article:published_time\" content=\"2016-11-11T09:12:03+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2016\/11\/pexels-photo-214221-e1478855500336.jpeg\" \/>\n\t<meta property=\"og:image:width\" content=\"1600\" \/>\n\t<meta property=\"og:image:height\" content=\"1067\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Jared Naude\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jared Naude\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/\"},\"author\":{\"name\":\"Jared Naude\",\"@id\":\"https:\/\/www.synthesis.co.za\/#\/schema\/person\/421c46fc0d94bad26008e0e3ccc42a93\"},\"headline\":\"Functional fun with TypeScript Generics\",\"datePublished\":\"2016-11-11T09:12:03+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/\"},\"wordCount\":1764,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.synthesis.co.za\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2016\/11\/pexels-photo-214221-e1478855500336.jpeg\",\"articleSection\":[\"News Room\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/\",\"url\":\"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/\",\"name\":\"Functional fun with TypeScript Generics - Synthesis\",\"isPartOf\":{\"@id\":\"https:\/\/www.synthesis.co.za\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2016\/11\/pexels-photo-214221-e1478855500336.jpeg\",\"datePublished\":\"2016-11-11T09:12:03+00:00\",\"description\":\"Read: 'Functional fun with TypeScript Generics' and more on the Synthesis blog for insights on the latest in the Tech and Software development industry.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#primaryimage\",\"url\":\"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2016\/11\/pexels-photo-214221-e1478855500336.jpeg\",\"contentUrl\":\"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2016\/11\/pexels-photo-214221-e1478855500336.jpeg\",\"width\":1600,\"height\":1067},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.synthesis.co.za\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Functional fun with TypeScript Generics\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.synthesis.co.za\/#website\",\"url\":\"https:\/\/www.synthesis.co.za\/\",\"name\":\"Synthesis\",\"description\":\"Specialized Software Development\",\"publisher\":{\"@id\":\"https:\/\/www.synthesis.co.za\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.synthesis.co.za\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.synthesis.co.za\/#organization\",\"name\":\"Synthesis, a Leading Software Development Company\",\"url\":\"https:\/\/www.synthesis.co.za\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.synthesis.co.za\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2016\/03\/Synthesis-logo.jpg\",\"contentUrl\":\"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2016\/03\/Synthesis-logo.jpg\",\"width\":1036,\"height\":220,\"caption\":\"Synthesis, a Leading Software Development Company\"},\"image\":{\"@id\":\"https:\/\/www.synthesis.co.za\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.synthesis.co.za\/#\/schema\/person\/421c46fc0d94bad26008e0e3ccc42a93\",\"name\":\"Jared Naude\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.synthesis.co.za\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2019\/01\/cropped-Jared-scaled-1-96x96.jpg\",\"contentUrl\":\"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2019\/01\/cropped-Jared-scaled-1-96x96.jpg\",\"caption\":\"Jared Naude\"},\"url\":\"https:\/\/www.synthesis.co.za\/author\/jared\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Functional fun with TypeScript Generics - Synthesis","description":"Read: 'Functional fun with TypeScript Generics' and more on the Synthesis blog for insights on the latest in the Tech and Software development industry.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/","og_locale":"en_US","og_type":"article","og_title":"Functional fun with TypeScript Generics","og_description":"Read: 'Functional fun with TypeScript Generics' and more on the Synthesis blog for insights on the latest in the Tech and Software development industry.","og_url":"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/","og_site_name":"Synthesis","article_published_time":"2016-11-11T09:12:03+00:00","og_image":[{"width":1600,"height":1067,"url":"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2016\/11\/pexels-photo-214221-e1478855500336.jpeg","type":"image\/jpeg"}],"author":"Jared Naude","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Jared Naude","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#article","isPartOf":{"@id":"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/"},"author":{"name":"Jared Naude","@id":"https:\/\/www.synthesis.co.za\/#\/schema\/person\/421c46fc0d94bad26008e0e3ccc42a93"},"headline":"Functional fun with TypeScript Generics","datePublished":"2016-11-11T09:12:03+00:00","mainEntityOfPage":{"@id":"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/"},"wordCount":1764,"commentCount":0,"publisher":{"@id":"https:\/\/www.synthesis.co.za\/#organization"},"image":{"@id":"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#primaryimage"},"thumbnailUrl":"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2016\/11\/pexels-photo-214221-e1478855500336.jpeg","articleSection":["News Room"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/","url":"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/","name":"Functional fun with TypeScript Generics - Synthesis","isPartOf":{"@id":"https:\/\/www.synthesis.co.za\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#primaryimage"},"image":{"@id":"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#primaryimage"},"thumbnailUrl":"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2016\/11\/pexels-photo-214221-e1478855500336.jpeg","datePublished":"2016-11-11T09:12:03+00:00","description":"Read: 'Functional fun with TypeScript Generics' and more on the Synthesis blog for insights on the latest in the Tech and Software development industry.","breadcrumb":{"@id":"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#primaryimage","url":"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2016\/11\/pexels-photo-214221-e1478855500336.jpeg","contentUrl":"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2016\/11\/pexels-photo-214221-e1478855500336.jpeg","width":1600,"height":1067},{"@type":"BreadcrumbList","@id":"https:\/\/www.synthesis.co.za\/functional-fun-typescript-generics\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.synthesis.co.za\/"},{"@type":"ListItem","position":2,"name":"Functional fun with TypeScript Generics"}]},{"@type":"WebSite","@id":"https:\/\/www.synthesis.co.za\/#website","url":"https:\/\/www.synthesis.co.za\/","name":"Synthesis","description":"Specialized Software Development","publisher":{"@id":"https:\/\/www.synthesis.co.za\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.synthesis.co.za\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.synthesis.co.za\/#organization","name":"Synthesis, a Leading Software Development Company","url":"https:\/\/www.synthesis.co.za\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.synthesis.co.za\/#\/schema\/logo\/image\/","url":"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2016\/03\/Synthesis-logo.jpg","contentUrl":"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2016\/03\/Synthesis-logo.jpg","width":1036,"height":220,"caption":"Synthesis, a Leading Software Development Company"},"image":{"@id":"https:\/\/www.synthesis.co.za\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.synthesis.co.za\/#\/schema\/person\/421c46fc0d94bad26008e0e3ccc42a93","name":"Jared Naude","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.synthesis.co.za\/#\/schema\/person\/image\/","url":"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2019\/01\/cropped-Jared-scaled-1-96x96.jpg","contentUrl":"https:\/\/www.synthesis.co.za\/wp-content\/uploads\/2019\/01\/cropped-Jared-scaled-1-96x96.jpg","caption":"Jared Naude"},"url":"https:\/\/www.synthesis.co.za\/author\/jared\/"}]}},"_links":{"self":[{"href":"https:\/\/www.synthesis.co.za\/wp-json\/wp\/v2\/posts\/7865","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.synthesis.co.za\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.synthesis.co.za\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.synthesis.co.za\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/www.synthesis.co.za\/wp-json\/wp\/v2\/comments?post=7865"}],"version-history":[{"count":0,"href":"https:\/\/www.synthesis.co.za\/wp-json\/wp\/v2\/posts\/7865\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.synthesis.co.za\/wp-json\/wp\/v2\/media\/836"}],"wp:attachment":[{"href":"https:\/\/www.synthesis.co.za\/wp-json\/wp\/v2\/media?parent=7865"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.synthesis.co.za\/wp-json\/wp\/v2\/categories?post=7865"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.synthesis.co.za\/wp-json\/wp\/v2\/tags?post=7865"},{"taxonomy":"ptype","embeddable":true,"href":"https:\/\/www.synthesis.co.za\/wp-json\/wp\/v2\/ptype?post=7865"},{"taxonomy":"sectors","embeddable":true,"href":"https:\/\/www.synthesis.co.za\/wp-json\/wp\/v2\/sectors?post=7865"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}