Tangential but coding in JS/TS, I often will go for object arguments to make things more readable. If you have a function like:
foo(arg1: boolean, arg2: boolean, arg3: boolean)
Then when you call it it will look like foo(true, false, true) which is not great for readability. Instead I move all the arguments into an object which makes each field explicit. Ie.
foo({ arg1: true, arg2: false, arg3: true })
This also carries the advantage that you can quickly add/remove arguments without going through an arduous refactor.
The only languages it supports are JavaScript, TypeScript, PHP, and Lua. I can confirm that it works for JavaScript and TypeScript, I haven't tried the other two.
A similar extension named "Inline Parameters Extended for VSCode" supports a different set of languages: Golang, Java, Lua, PHP, and Python. It seems to be a fork of the aforementioned.
One of the things that's often not considered with these kind of interfaces, is whether or not they're actually possible. For instance, arg3 might only be true if arg1 is also true. Or arg3 may not be false if both arg1 and arg2 are also false.
Using object arguments is a great start, and I think using enums can also be powerful (if you're using string literal types). But often times I reach for explicit interfaces in these situations. IE:
This provides semantic benefits in that it'll limit the input to the function (forcing callers to validate their input), and it also provides a scaffold to build useful, complete test cases.
foo(arg1: boolean, arg2: boolean, arg3: boolean)
Then when you call it it will look like foo(true, false, true) which is not great for readability. Instead I move all the arguments into an object which makes each field explicit. Ie.
foo({ arg1: true, arg2: false, arg3: true })
This also carries the advantage that you can quickly add/remove arguments without going through an arduous refactor.