Classes with static arrow functions

I'm currently implementing the static land specification (an alternative of fantasy land). I want to not only use plain objects as types but also ES2015 classes with static methods. I've implemented these static methods as arrow functions in curried form instead of normal functions. However, this isn't possible with ES2015 classes:

class List extends Array {
  static map = f => xs => xs.map(x => f(x))
  static of = x => [x]
}

My map doesn't need its own this, because it is merely a curried function on the List constructor. To make it work I have to write static map(f) { return xs => xs.map(x => f(x)) }, what is very annoying.

  • Why can't I use arrow functions along with an assignment expression in ES2015 classes?
  • Is there a concise way to achieve my goal anyway?

Answers:

Answer

Why can't I use arrow functions along with an assignment expression in ES2015 classes?

Because that's just not how the ES2015 class syntax is designed — for now, see under the line below.

Is there a concise way to achieve my goal anyway?

It's not clear to me that you want classes at all, just an object:

const List = {
  map: f => xs => xs.map(x => f(x)),
  of:  x => [x]
};

(You've said that extending is important to what you're doing.)

But if you want List to extend Array (e.g., you will have instances) but then add these statics to it, you'll need a two-step:

let List = Object.assign(
  class List extends Array { },
  {
    map: f => xs => xs.map(x => f(x)),
    of:  x => [x]
  }
);

console.log(List.of(42)); // [42]

If you want them non-enumerable or non-configurable, etc., you'll want Object.defineProperties rather than Object.assign; I'll leave that as an exercise for the reader...


There's a Stage 3 proposal for class "fields," including static fields, which is being actively implemented by JavaScript engine builders. (And you can use it now via tools like Babel.) It provides static field declaration syntax within the class, almost exactly the way you showed them:

// Not in the language yet, but at Stage 3 and shipping without
// any flags in V8 (for instance, in Chrome)
class List extends Array {
  static map = f => xs => xs.map(x => f(x));
  static of = x => [x];
}

console.log(List.of(42)); // [42]


Note: There's a standard Array.of method, so I wouldn't add an incompatible of to that List.

Finally, I should note that unless there's some reason they have to be arrow functions, ES2015's class syntax supports static methods:

// ES2015+
class List extends Array {
  static map(f) {
    return xs => xs.map(x => f(x));
  }
  static of(x) {
    return [x];
  }
}

console.log(List.of(42)); // [42]

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.