TypeScript Version: 2.4.1
Code
class Component {
render(): boolean {
return false;
}
}
class App extends Component {
render = () => false;
}
Expected behavior:
Compiles correctly.
Actual behavior:
The compiler reports an error:
test.ts(7,3): error TS2424: Class 'Component' defines instance member function 'render', but extended class 'App' defines it as instance member property.
I know this may be designed, a feature rather than a bug, but such behavior is quite weird.
There are good reasons not to allow the reverse case, but I can't remember why we disallow this. I think it's come up before but will take it up as a suggestion
An arrow fonction has no prototype or even a name. This is a good reason why they shouldn't have the same type.
Also, in the base class, the method is part of the classes prototype. You are overwriting it with a property initialiser that gets desugared in the constructor and isn't actually part of the prototype chain. You end up with differences in own properties at run time, so they are effectively, subtly different, though the shape is the same. At runtime, the shape of the Class.prototype is actually different, though I believe TypeScript includes the shape of properties in the type of the prototype, even though they aren't really there.
I thought you might also get into trouble with super but actually that seems fine.
Easy PR if someone wants to submit one.
I would like to work on this one.😅
@RyanCavanaugh @kitsonk i have some question
class Component {
render(): boolean {
return false;
}
}
class App extends Component {
get render () {
return () => true
}
}
@Kingwl
@RyanCavanaugh
@Kingwl
I don't think it makes sense to “override” a method – which in general can have any signature – with an accessor, which can be thought of as a group of methods with two overloads, one get: () => T and one set: (T) => void.
However overriding a method with an equivalent arrow function is an useful shorthand and seems like a good idea to me. I think the right approach would be to convert the arrow function to the “full form” and treat it as a normal method (i.e. add it to the prototype, let it have a name, …).
The only problem I can think of is that we could decide to implement a C#-like syntax for method shorthands. The new syntax would be preferable to this one and we would have to deprecate it.
Here's a comparsion of the current and possible syntaxes:
// Current full-body syntax
class A {
function foo() { return 42; }
}
// Current lambda syntax
class B {
foo = () => 42;
}
// @coderfox's Arrow extension proposal
// compiles to the full-body function
class C extends A {
foo = () => 1/0;
}
// C#-like expression-bodied method
// compiles to the same code as A
// is more elegant and clearer than B
class D {
foo() => 42;
}
// Extending with an exp.-bodied method
// no problem, uncontroversial
// works automatically as long as D works
class E extends A {
foo() => 1/0;
}
@RyanCavanaugh @xtuc @kitsonk What are your opinions on this? Is the possibility of implementing expression-bodied functions enough to pass over @coderfox's syntax?
@m93a Class properties and arrow functions are both TC39-controlled entities now; proposals about new syntax that combine the two belong on ES Discuss or other forums.
Overriding a method (instance member function) with an arrow function (instance member property)... Will the context, this, be different depending on what the actual object is?
Also, arrow functions can't be called with super.foo(). In the example of @coderfox, what would happen if I extend the class App and execute super.render()?
I have still not seen an overriding method that needed to be written that way. You end up with something less efficient by doing so. I think that might've been the original motivation.
This error TS2424 happens for me with TypeScript 2.9.2, but not with TypeScript 3.0.1.
Can't find the PR for this but it does appear to have been fixed.
I get this error now with 3.7.0-dev.20191011.
Not getting this error with 3.6.2.
Did something change?
TypeScript Version: 2.4.1
Code
class Component { render(): boolean { return false; } } class App extends Component { render = () => false; }Expected behavior:
Compiles correctly.
Actual behavior:
The compiler reports an error:
test.ts(7,3): error TS2424: Class 'Component' defines instance member function 'render', but extended class 'App' defines it as instance member property.I know this may be designed, a feature rather than a bug, but such behavior is quite weird.
Do we have solution for this m also stuck in such issue
Most helpful comment
Can't find the PR for this but it does appear to have been fixed.