Access 2 arguments in a function out of order? - javascript

Say I have a function that has (A, B, C, D, E) arguments.
Foo(A, B, C, D, E)
But I don't need them all the time. Sometimes I just need A and C for example. Right now I would have to call it like this:
Foo('beef', '', 'sour cream', '', '')
But those blanks irritate me. Is there a way to say to make it just be Foo('beef', 'sour cream')?
Maybe Foo(A='beef', C='sour cream')?
I've tried making them optional, but as I understand it, I can't expect the program to understand I want B blank. It expects 5 arguments, it needs 5.

You can name them like this:
function foo({A, B, C, D, E}) {
}
foo({A:3, D:5})
What we're technically doing here is passing an object, and using destructuring to extract the properties of the object into local variables.

Related

Typescript - Use element in array argument as return type

I have a simple function as follow:
const transform = ([a, b]) => ({operation: a, ...b});
How can I type this function to make sure the return type is an object containing a key operation with the type of the argument a and the property of b.
I tried the following but without success:
function transform<[A, B]>(param: [A, B]): { operation: A } & B {
return { operation: param[0], ...param[1] };
}
Any help about that? Thanks!
You have what amounts to a typographical error; instead of transform<[A, B]>(...), you need to write transform<A, B>(...) like this:
function transform<A, B>(param: [A, B]): { operation: A } & B {
// ----> ^^^^^^ ^ ^ <------------> ^ ^
// declaring type params using the type params
//
return { operation: param[0], ...param[1] };
}
The transform() function is generic in two type parameters A, and B. (You can think of these almost like regular function parameters, but instead of corresponding to arguments that callers pass in as values, they are arguments that callers pass in as types.) The syntax for declaring the list of type parameters a generic function takes is to put a comma-separated list of these parameters inside angle brackets, immediately before the list of regular parameters in parentheses.
It's only later in the function signature and implementation where you use the type parameters as types. So the param function parameter is annotated as type [A, B], a tuple type where the first element is of type A and the second element is of type B. The fact that you were going to use the type [A, B] has nothing to do with the syntax to declare the type parameters.
That's the answer to the question as asked.
I could go a little further and suggest that a more direct translation of your original transform JavaScript code into TypeScript would look like this:
const transform = <A, B extends object>(
[a, b]: [A, B]
): { operation: A } & B => ({ operation: a, ...b });
Here you can see that even arrow functions can be generic, and therefore need a type parameter declaration before the parameter list (which must be in parentheses, even if your arrow function looks like x => x... you can't write <T>x:T => x, you need <T>(x: T) => x). Also see that the return type annotation of an arrow function comes immediately after the parameter list with a colon, and before the arrow =>.
Since you are going to use object spread on b which of type B, it's useful to tell the compiler that B should be constrained to the object type, so that nobody calls transform([1, 2]) and is possibly confused by what comes out.
Also, you can still use destructuring assignment in your function parameter, so we have ([a, b]: [A, B]) instead of (param: [A, B]).
Playground link to code

Concise way of defining ES6 symbols?

If I want to define multiple symbols in a row, the syntax is a little verbose:
const a = Symbol('a'),
b = Symbol('b'),
c = Symbol('c');
I came up with a slightly more concise way to do it:
const [a, b, c] = ['a','b','c'].map(key => Symbol(key))
Is that the most concise way possible, or is there some dedicated syntax for declaring multiple symbols that I'm unaware of?
P.S. 'a' 'b' and 'c' are just arbitrary examples of course. I realize that one could get clever with this particular example ;)
There's a fun part of FP that you might be missing out on, which is that in a pure system, you can always replace an anonymous function with a named reference which is returned (and more generally, you can always replace a function with the value it would have returned), assuming that the function you're replacing and the function you're replacing it with take the same number of arguments.
const [a, b, c] = ["a", "b", "c"].map(Symbol);
Should work just fine, as long as you keep in mind that you can cause accidents here, by passing in functions that expect more than 1 argument.
Sure, not much more terse than what you already had. ...but still more than none.
It can be as concise as
const [a, b, c] = ['a','b','c'].map(Symbol);
There's no way to skip abc tautology here because variable names should be explicitly written, as well as symbol description.
Symbol descriptions are helpful for debugging. If they can be omitted (not recommended), it becomes
const [a, b, c] = [,,].map(Symbol);
for fixed amount of variables. And
const [a, b, c, d /*, ... */] = function* () { for(;;) yield Symbol() }();
for unlimited amount of variables.
One option, if you don't mind using ES6-only features that can't be polyfilled, is to use a Proxy that returns a symbol for each property access. You could make a helper module file like
module.exports = function autoSymbols() {
return new Proxy({}, {
get(target, name, receiver){
return Symbol(name);
},
});
}
then do
const {a, b, c} = require('./auto-symbols');
though personally I think enumerating the Symbol instances manually is more easily maintained.

Dynamically create an object as needed without if checks

So I thought I was crazy, and I may be but this seems pretty simple. Say I have this bit of code:
let a = {};
a.b.c.d.e.f.g = 'Something Awesome';
Now you can imagine the if-check nightmare that would have to take place to see if each level exists. And even if I had a fancy looping way to do it, someone else has had to think this up.
I think CoffeeScript had something like this, but I can't seem to find anything on it. I was also wondering if there was an ECMAScript6 or lodash way of doing the same type of thing?
Maybe something like:
set(a, b, c, d, e, f, g, 'Something Awesome');
And in that case even:
set(a, b, c, d, {e: {f: {g: 'Something Awesome'}}});
But the last option would wipe out anything that may exist in e, f, and g.
You are referring to lodash's _.set():
const a = {};
_.set(a, 'b.c.d.e.f.g', 'Something Awesome');
console.log(a);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

JavaScript how to use (single value) easing functions

So I found several implementations of the following type of easing functions:
function easeInQuad(t, b, c, d) {
return c*(t/=d)*t + b;
}
but would really like to use the following format instead:
function easeInQuad(pos) {
return Math.pow(pos, 2);
}
How to calculate "pos" ?
Thanks in advance.
EDIT:
They are indeed 2 different functions.
The first expects t: current time, b: beginning value, c: change in value, d: duration
The second expects some calculus to be made beforehand in order to do the same as the first.
I'm trying to find out what are those calculus.
EDIT 2:
I believe I haven't explain my self properly and apologise for that.
Let me put it this way:
How to use the following:
https://github.com/danro/easing-js/blob/master/easing.js

Using a rest parameter before the last parameter in function definition

My problem is best explained with a simple code example:
function doThing(a, ...b, c) {
console.log(a, b, c)
}
doThing(1,2,3,4); // Expect "1 [2,3] 4"
This instead gives a syntax error Unexpected token, pointing to the comma after the b in the function definition.
Is it not possible to put a single parameter after a 'rested' parameter with ES6? If not, any idea why? It would be really useful for me. Thanks!
Edit: I initially thought that doThing(a, ...b, c) would be completely unambiguous, but I see now that doThing(1,2,3) would need an arbitrary rule to decide whether the 3 goes in b or c (i.e. if we pass a number of params that is less than or equal to the number of params in the function definition).
developer.mozilla.org says:
If the last named argument of a function is prefixed with ..., it becomes an array whose elements from 0 to theArgs.length are supplied by the actual arguments passed to the function.
Actually this feature of ES6 is called Rest parameters so it is meant to be the last in the list of parameters.
So this code will work:
function doThing(a, b, ...c) {
console.log(a, b, c);
}
doThing(1,2,3,4);

Categories