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?
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
If everything's static, why the
extends Array
? – T.J. Crowder Commented Aug 22, 2016 at 12:51 - possible duplicate of stackoverflow./questions/32545495/…? – Bergi Commented Aug 22, 2016 at 12:56
- @T.J. The idea is to make an existing library static land patible. So there will be classes with non-static properties, which must be extended. – user6445533 Commented Aug 22, 2016 at 12:57
1 Answer
Reset to default 15Why 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 inpatible 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]