Classes with static arrow functions

2019-02-12 20:38发布

问题:

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?

回答1:

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:

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

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 2 proposal for class "fields," including static fields. If it progresses through to stage 4, eventually it will be part of an upcoming language specification (perhaps ES2018; unlikely at this point to make ES2017 but you never know).

It would allow static fields declared within the class, almost exactly the way you showed them:

// NOT IN THE LANGUAGE YET, BUT A PROPOSAL AT STAGE 2
class List extends Array {
  static map = f => xs => xs.map(x => f(x));
  static of = x => [x];
}

If you transpile with Babel, you can tell it to include Stage 2 proposals.