Reputation: 21400
Starting from ES6 classes can extend special objects like functions, arrays and primitive's wrappers. It's simple: just write a class that extends corresponding type and use it:
class MyNumber extends Number {
constructor() {
super(42)
}
square() {
return this ** 2
}
}
var x = new MyNumber()
console.log(typeof x, x + "", x.square() + "")
But EcmaScript also has some new types like Symbol
and BigInt
. They still have a non-primitive wrapper types, but you can't use them as constructor and need to explicitly wrap primitive into an object:
var x = BigInt("42")
var y = Object(x)
console.log(typeof x, x + "", x + 1n + "")
console.log(typeof y, y + "", y + 1n + "")
try {
var z = new BigInt("42")
} catch (e) {
console.log(e.message)
}
What if I want to extend such wrapper? Defining a class works fine, but if I try to create an object, it throws on super
call:
class MyBigInt1 extends BigInt {
constructor() {
super("42")
}
}
try {
var x = new MyBigInt1()
} catch (e) {
console.log(e.message)
}
class MyBigInt2 extends BigInt {
constructor() {
}
}
try {
var x = new MyBigInt2()
} catch (e) {
console.log(e.message)
}
Upvotes: 1
Views: 205
Reputation: 664559
From the spec:
The
Symbol
constructor […] is not intended to be subclassed.
And similarly from the BigInt proposal:
The
BigInt
constructor is not intended to be used with thenew
operator or to be subclassed.
Instantiating primitive wrappers is already bad enough, don't go extending them.
A hack would be to not call super()
(which you cannot prevent from throwing), but create the object yourself (without new
) and then set its prototype to your custom one. Just like you already did it in your answer :-)
Upvotes: 1
Reputation: 21400
I've found a possible solution, but still searching for a better way:
class MyBigInt extends BigInt {
constructor() {
var res = Object(BigInt("42"))
Object.setPrototypeOf(res, new.target.prototype)
return res
}
square() {
return this ** 2n
}
}
var x = new MyBigInt()
console.log(typeof x, x + "", x.square() + "")
And same approach with Symbol
class MySymbol extends Symbol {
constructor(description) {
var res = Object(Symbol(description))
Object.setPrototypeOf(res, new.target.prototype)
return res
}
smth() {
return `(${this.description})`
}
}
var x = new MySymbol("qqq")
console.log(typeof x, x.description, x.smth())
var y = { [x]: 42 }
console.log(y[x], y[x.toString()])
Upvotes: 0