I used to be like that, but after a lot of JS programming I ended up with WebStorm and very heavily using JSDoc and Closure compiler syntax inline type-comments - which together with WebStorm give me almost TypeScript-like type checks. There is not a variable or function parameter declaration without a type in my code now.

Example (the inline type info is Closure compiler syntax, with the "@" it's JSDoc):

/**
* @typedef {Object} MyResultType
* @property {string} example
* @property {Function} exampleFn
*/

const /**string[]*/ myPromise = Promise.resolve(['','']);
const /**MyResultType*/ t = myPromise.then(
/**string[]*/ a => a.map(/**string*/ s => s.toUpperCase())
);

Or a more lengthy JSDoc comment when I need to document a variable anyway:

/**
* This is a very important and beautiful variable
* @type string[]
*/
const myPromise = Promise.resolve(['','']);

I have a lot of complex return types - meaning an object instead of a simple type, because a function can only return one value and I often have to return more than that. I also have lots of promises (also as return values), and it's easy to get confused which function returns a result synchronously and which one asynchronously.

Sync. vs. async. isn't something logical and obvious - it's determined by where you get data from. No coding construct won't change that we have to keep the hardware in mind and concentrate on just the algorithm when we don't have blocking function calls, "yield" and "async" don't change that, we have to remember to add them. So having difficulty remembering which function returns the result this or that way has nothing to do with the algorithm and I appreciate the IDE (in my case, or TypeScript in others) keeping track of the types.

Even though I don't use TypeScript I use TypeScript "DefinitelyTyped" interface definitions for things like Node and Mocha - WebStorm uses them for its behind the scenes type-checking.

By religiously always adding a type even when it seems obvious I get WebStorm to report when a type doesn't match what it determined should be there, and it's meta-information for myself. It always ensures that I always get correct auto-completion suggestions and inspection warnings - because the IDE isn't always capable of resolving all variables. Especially when it's promises created in another module and after the n-th chain element and in connection with arrow functions and parameter destructuring the IDE often gives up, there still are gaps in its ability to find the intended type since those constructs are too new. However, each time I find a hole I file a bug report and the JetBrains team almost fixes it pretty quickly for the next version. "Flow" is supported too. Example for the type of bugs one may find, and how a type inspection error looks like (randomly picked from the bug list): https://youtrack.jetbrains.com/issue/WEB-21839#u=14643829544... (that bug has been fixed)

I did a little bit of TypeScript, WebStorm support is very good there too. I try to avoid adding a compilation step but it sure looks tempting - and just a year or two ago I was adamantly against it as "useless". Well, my attitude has changed after having fond types very convenient on a large exploratory project where I often have to revisit and refactor and often completely rewrite previously written code and/or restructure large sections and multiple modules at a time.

I'm not saying you absolutely must use types, it's just that many people incl. myself find it more convenient, and in my case I even was in the other camp for the longest time.