Hacker News new | ask | show | jobs
by disillusionist 426 days ago
I started using this pattern years ago and haven't looked back. React components are defined using a single properties param and it feels natural to extend the practice to other methods and helper functions that I write.

One nice unexpected side effect is that I end up with more consistency in variable naming when using a param object in order to benefit from object definition shortcuts.

ie I will usually write something like

  const firstName = getFirstName(); doTheThing({ firstName });
rather than

  const fName = getFirstName(); doTheThing({ firstName: fName });
2 comments

What bothers me a lot is that return values can't have a name. Suppose I have a function

string combineName(string first, string last);

Okay, I assume the result is the full name, but I don't really know that like I would if the return had a name in the header. (The function can be getFullName, yes, but that's so simple it doesn't matter).

you can do this rather easily by returning an object rather than a primitive. if you're using a language like TypeScript, destructuring the resulting returned object is rather trivial and (in my opinion) delightful to read. eg

  function combineNames({ first, last }) {
    const fullName = `${first} ${last}`;
    return { fullName };
  }
  const { fullName } = combineNames({first: 'John', last: 'Doe' });
For some reason React prefers to return arrays. I never understood the reason.

  const [state, setState] = useState(initialState)
instead of

  const {state, setState} = useState(initialState)
Some languages allow to define type alias, name of this type can be self-explanatory:

  type FullName = string;
  function combineName(first: string, last: string): FullName;
Also documentation comment for function is what specifically solves this - describes what function does and returns.
Neither really addresses the issue. Making a type for a single kind of string seems like an abuse of types just to shoehorn the documentation in. Documentation can be used directly of course, but that moots all of this -- just document? Yeah, but naming the variable is super quick compared to either.
Variable names is just documentation. Having types that can assert some condition on the underlying value is not even comparable to "having a named return variable". (just document? just name variables?) You don't care about what the name of the returned value is, you care about what *it is*.
Typescript nukes primitive aliases like this sadly. Intellisense will just infer it as "string".
Similarly to passing an object argument, you can return an object.

Then pair it with destructuring assignment!

`const { fullName } = getName({ firstName, lastName )}`

I fail to see the distinction, for documentation purposes, of this versus just giving it that `getFullName` function name.

A more complex example will probably return a more complex type that is more self-documenting. If the type is a single scalar value then I don't see the value of adding another name here.

Name the function/method as the thing it "returns".

In fact, just forget that it is a function that does something. Treat it as the thing it returns.

string fullName( string firstName, string lastName )

Likewise. Even if the input object only has a single property, I'll still use this pattern.
Another common pattern is to put the "primary" argument first, and the rest in an "options" object argument.
It works fine when your function takes a single primary argument—like `getLastWord(word: string, options?: TGetLastWordOptions): string | undefined`. The function name makes the purpose clear, and with just one main argument, it’s easy to follow. Sure, you're still "guessing" what the first parameter is but it’s not a heavy mental lift. You could argue that as long as you're consistent, using positional arguments in binary functions is fine–the pattern is clear and predictable.

But in the example from the OP, there isn’t really a primary argument. You're dealing with multiple values that carry equal weight, which makes positional arguments harder to reason about at a glance.

because i'm likely going to refactor this function "tomorrow" with additional properties. :)