Function to format numbers with thousand separators and decimals
You can use default parameters to automatically assign a value if none is given.

function neat(numToFormat, thousandSep = ".", decimalSep = ",")


You should start by checking if the input is valid, instead of doing it at the end. It would also be better to throw an error, since it's not easy to tell from the result if the formatting succeeded or not.

if (typeof numToFormat == 'number') {
  if(Number.isNaN(numToFormat) || !Number.isFinite(numToFormat)) {
    throw new Error("Invalid number");
  }
}
else if(typeof numToFormat == 'string') {
  if(!/^\d+((,|\.)\d+)?$/.test(numToFormat)) {
    throw new Error("Invalid string");
  }
}
else {
  throw new Error("Can only use number or string");
}


It's not parseFloat() which is imprecise, but the numbers themselves. JavaScript uses IEEE 754, which is 64-bit floating point numbers, with 53 bits used for precision. The number you are testing against is the highest safe integer, which is 2^53-1 and can be gotten from Number.MAX_SAFE_INTEGER. But your result could still be imprecise with numbers this large, since you are not only using integers but also 2 decimal places.

With string inputs you can get around this by not converting it to a number at all. Since the result is also a string, you can keep it a string all the way through. For number inputs you can only work with the precision you've been given. Any imprecision should be handled by the code calling this function beforehand.

You will need to update your parseInput function to avoid parseFloat. Just cut of any extra decimals, or add them if they are missing. If you want to round the number it gets a bit harder, but it's still possible.

Your placeThousands function can be done a little simpler. There are several ways to do it, but I would cut the string into an array of chunks and then join them together. I would also make it easier to change the chunk size by putting it in a variable.

const chunkSize = 3;
let chunks = [];
let start = wholesPart.length % chunkSize;
if(start != 0) {
    chunks.push(wholesPart.slice(0, start));
}
for(let i = start; i &lt; wholesPart.length; i+= chunkSize) {
    chunks.push(wholesPart.slice(i, i + chunkSize));
}
return chunks.join(thousandSep)


When I saw fstChunk the first thing I thought was 'fast chunk', but I guess it's supposed to be 'first chunk'. There is no reason make things less clear just to save 2 characters.

You don't need to check the length of wholesPart, placeThousands can handle short strings.

return placeThousands(wholesPart) + decimalPart;