Simple Cookie Service - Returns value of cookie based on cookie name passed in Introduction

So I have written a simple service that, when loaded, reads all of the cookies in the document, reduces them to a simple object where the cookie name is the key, and the cookie value is the value, and then allows you to get a cookie by name by checking cookies[cookieName].

It works great, but I guess my biggest questions are:

Questions


Where can I improve the code of course
Is it worth optimizing the code to use a for loop instead of reduce, or is it better to leave the code more succinct by using reduce? 
Will most developers know what reduce does? Should I update the code to use for simply to make it easier for other team members to understand what the code does?


But of course, feel free to pick it apart however, I'm always up for learning better ways of coding.

Other Stuff

I'm sure this code could be enhanced by allowing the setting of cookies as well, but for now my needs are simply to read cookies as my application should never be adding or modifying cookies. Therefore set functionality was intentionally left out to discourage those implementing the class from doing so.

The Code

export class CookieService {

    // Constructor
    constructor(){

        // Initialize the cookie service
        this.init()
    };

    // Holds the resulting cookies object after init is run
    cookies: any;

    // Initializes the cookie service by getting all cookies on the document and creating an object that holds each cookie by name in a key/value pair
    init: Function = () =&gt; {

        // Get the document cookie
        this.cookies = document.cookie

            // Split it on the ";" character to get each individual cookie in an array
            .split(";")

            // Reduce the array into an object
            .reduce(

                // Pass in the cookies object and the current value to the reduce callback function
                ( cookies, currentValue ) =&gt; {

                    // Split the cookie into key and value
                    let cookie = currentValue.split("=");

                    // Sanity check to make sure we got two values from the split and each value has a length.  Filters out malformed cookies.
                    if ( cookie.length === 2 &amp;&amp; typeof cookie[0] === "string" &amp;&amp; cookie[0].length &amp;&amp; typeof cookie[1] === "string" &amp;&amp; cookie[1].length ){

                        // Get the key. Trim removes any spaces from the resulting key to ensure proper matches.
                        let key = String(cookie[0]).trim();

                        // Get the value.  Trim removes any spaces from the resulting value to ensure proper matches.
                        let value = String(cookie[1]).trim();

                        // Set the new cookie on the cookies object
                        cookies[key] = value;

                        // Return the new cookies object
                        return cookies;
                    }
                }, {}
            )
    };


    // Gets a cookie from the cookies object
    getCookie: Function = cookieName =&gt; {

        // If we have a cookies array, and the requested cookie exists
        if ( typeof this.cookies !== "undefined" &amp;&amp; this.cookies[cookieName]){

            // Return the requested cookie
            return this.cookies[cookieName];

        } else {

            // Otherwise return false to let the requester know the cookie was not found
            return false;
        }
    }
}
Re using reduce(): There are many Javascript programmers who like to find clever ways to use this method, and your pattern is probably popular among them. I'm not one of them. I would use forEach() instead, and assign to this.cookies[key] within it. But if you like reduce(), that should be fine; it's a common enough pattern that you shouldn't have to worry about other programmers not understanding it.

However, there's a bug in the way you're using reduce(). The callback function has to return a result every time, but your function only returns in the if block. You should move return cookies; outside the if.

You have some unnecessary code when expanding currentValue. 
String.prototype.split always returns an array of strings, so it's not necessary to test if typeof cookie[i] == "string". And once you have tested this, it's not necessary to use String(cookie[i]). You don't have to go overboard on defensive coding.

When returning the cookie, you can simplify the code. It's not necessary to test the value and then return false if it's not truthy; you can simply return the value, and if it doesn't exist you'll return undefined, which is just as falsey as false. And rather than test specifically for typeof this.cookie == "undefuned", you can just test if the property is truthy (if you want to be really defensive, you could go the other way and test whether it's actually an array).

Since you're using other EcmaScript 6 features, you could use destructuring of the split() assignment, rather than referring to cookie[0] and cookie[1] repeatedly. Then you can simplify the validation checks -- all the invalid values are also falsey, so if (key &amp;&amp; value) will suffice.

export class CookieService {

    // Constructor
    constructor(){

        // Initialize the cookie service
        this.init()
    };

    // Holds the resulting cookies object after init is run
    cookies: any;

    // Initializes the cookie service by getting all cookies on the document and creating an object that holds each cookie by name in a key/value pair
    init: Function = () =&gt; {

        // Get the document cookie
        this.cookies = document.cookie

            // Split it on the ";" character to get each individual cookie in an array
            .split(";")

            // Reduce the array into an object
            .reduce(

                // Pass in the cookies object and the current value to the reduce callback function
                ( cookies, currentValue ) =&gt; {

                    // Split the cookie into key and value
                    let [key, value] = currentValue.split("=");

                    // Sanity check to make sure we got two values from the split and each value has a length.  Filters out malformed cookies.
                    key = key &amp;&amp; key.trim();
                    value = value &amp;&amp; value.trim();
                    if ( key &amp;&amp; value ){

                        // Set the new cookie on the cookies object
                        cookies[key] = value;

                    }

                    // Return the updated cookies object
                    return cookies;

                }, {}
            )
    };


    // Gets a cookie from the cookies object
    getCookie: Function = cookieName =&gt; {

        // If we have a cookies array, and the requested cookie exists, return it
        return this.cookies &amp;&amp; this.cookies[cookieName];

    }
}