Source: lang/getStringSafely.js

import isNullish from './isNullish';

/**
 * @function getStringSafely
 * @description A safer version of toString(). To avoid getting 'NaN' or other
 * non-real string values. It will coerce strings out of booleans,
 * numbers, objects with their own toString() function, and of course
 * strings.
 *
 * @parent Lang
 *
 * @param thing {Boolean|String|Object} thing to be converted to string.
 * @return {string|null} the coerced string, null if unable.
 */
export default function getStringSafely(thing) {
    const type = typeof thing;

    // it is already a string, return it.
    if (type === 'string') return thing;

    // if it is nullish, return null.
    if (isNullish(thing)) return null;

    // convert numbers and booleans to strings.
    if (type === 'number' || type === 'boolean') return String(thing);

    // it is an object with it's own toString implementation. Hopefully it is meaningful.
    if (
        type === 'object' &&
        Object.prototype.hasOwnProperty.call(thing, 'toString') &&
        typeof thing.toString === 'function'
    ) {
        return thing.toString(thing);
    }

    // it is an object without it's own toString implementation. Let's JSON.stringify() it
    if (
        type === 'object' &&
        !Object.prototype.hasOwnProperty.call(thing, 'toString')
    ) {
        return JSON.stringify(thing);
    }

    // no telling what it is, return null.
    return null;
}