-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Getters and methods implicit return types should be recomputed upon inheritance. #57365
Comments
#38008 is for methods, not sure if thereβs a duplicate for getters |
This could help in some cases, although you still need to know the returned type (which can be tricky), and to explicitly add it in the children classes. It'll be better if an implicit return type could make it auto-magically. Or to have a keywork like "infer" to tell TS to re-infer the return type upon inheritance. In other cases, it would be impossible to use as some types are currently impossible to describe in TS (e.g. when it requires generic instantiation of a type or when TS widen types). I use another workaround : abstract class Base {
protected _foo: string|number = 42;
abstract readonly foo: typeof Base["_foo"];
}
class Child extends Base {
protected _foo = 42; // numbers
override foo = this._foo; // requires to "re-implement" the public RO prop in each sub-classes.
} |
You've got abstract class Base {
abstract _foo: number | string;
get foo(): this["_foo"] {
return this._foo;
}
}
class Child extends Base {
override _foo = 4;
}
let c = new Child();
let foo = c.foo; // number The problem with "auto-magic" or "infer" is that it sounds like you want the compiler to do a lot of extra work that might not scale. Essentially you're either asking for all classes to be implicitly generic (which is essentially what polymorphic But these are just my opinions, we'll see what the TS team says. |
Thanks for your answer.
Yep, that is one of the issue. The other is that from Maybe one workaround is to make the member public but name it with a symbol ?
I'm starting to think that all issues I had recently comes from TS type widening inside function body... foo(): infer {
return this._foo; // return type is typeof this._foo
// type FooReturnType<T extends typeof this._foo> = T
} The return type could be partially pre-computed at the class level, to not do too much extra-computations on each calls ? |
Maybe something like that could be acceptable ? class Child {
override foo: infer; // override: ensure "foo" exists in the base class.
// infer, an opt-in to recompute the type (for an attribute) or the return type (for a getter or method).
} Also, you talked about scalability, I understand for the auto-magically option, but I do not understand why an opt-in like: class Base {
get foo(): infer {} // e.g. if no "foo" in children classes, adds a `override foo: infer;` to it ?
} Would cost more than a : class Child extends Base {
override get foo() {
return super.foo as typeof this._foo // <- you also need to recompute the return type.
}
} |
Sounds like #10570. |
I don't think so. #10570 is about the type of attribute that are recomputed from the initializer expression, leading to troublesome behavior when initializing them to |
This violates the principle that you can (almost always) move a piece of code across the |
? But you still have access to the base class methods' return type, no ?
|
There's nothing simple about this at all, that's the problem |
Then, if it is not possible, could it be possible to at least be able to override foo(...): Child;
// or
override foo(...): Child = inherit; // we explicitly state we do not provide an implementation. It will help a little for some cases. And to be able to use
? |
This issue has been marked as "Too Complex" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
π Search Terms
inheritance getter and attribute inconsistency
β Viability Checklist
Sorry it's me again, but I'm still having issue with TS lack of precision on return types.
β Suggestion
Getter/method implicit return type should be recomputed upon inheritance.
Alternatively, a way to indicate we want the return type to be recomputed should be provided e.g. something like :
class Base { get foo(): infer {...} }
) orclass Child extends Base { foo: infer; }
.I think the current behavior may lead to undetected bugs.
The suggestion I make may not be the best one, but I think the issue does exist.
This behavior is inconsistent with the behavior of attributes upon inheritance, which is confusing:
π Motivating Example
Playground Link
π» Use Cases
Too verbose, potentially risky, and a pain to do so on each of the inherited classes:
For complex types, could be tricky to write, and could break encapsulation (i.e. may require to know how the returned value is computed to deduce what its type should be).
Or even worst:
The text was updated successfully, but these errors were encountered: