Repository: TypeScript
Issue: `inherit` keyword as shorthand to refer to super class fields and methods.
Labels: Suggestion,In Discussion

## Search Terms

Inherit, inheritance, type inference, subclass, superclass, override, 

## Suggestion

This issue addresses the lack of easy way to refer to types of fields or methods of a base class or implemented interfaces without a high amount of repetition.  Proposed is a keyword `inherit` which will act as a type alias which is contextually resolved for the corresponding type of the base class.

A simpler way to understand this proposal is to think of it as a solution to #10570 by offering an explicit but convenient way to refer to the base class, let us look at a typical example:

```typescript
abstract class Geometry {
    public abstract model: "square" | "circle";
}

class Canvas extends Geometry {
    // initially set to square but still allow to change to circle later.
    public model = "square";
    // ERROR  ^ Type 'string' is not assignable to type '"square" | "circle"'
}
```
In this case we want to preserve the same type for field `model` from the class `Geometry`. the most obvious solution is to rewrite `"square" | "circle"` but we can do a little better by instead using `Geometry["model"]` to allow for changes in the base class to propagate automatically.

```typescript
class Canvas extends Geometry {
    public model: Geometry["model"] = "square";
    //  This way we explicitly inherit the same type as base class.
}
```
This is better but still requires us to refer to the base class and rewrite the field name for each field initialized in this way. The proposed solution is to add a keyword `inherit` which will use the base class and the field name to resolve to the appropriate type.  
```typescript
class Canvas extends Geometry {
    public model: inherit = "square";
    //  This would be equivalent to above example using Geometry["model"]
}
```
Here is an [example playground](https://www.typescriptlang.org/play/index.html#code/C4TwDgpgBAYgrgOwMZQLxQBQDocEMBOA5gM4BcUuCIA2gLoCUaAfBVQNwBQHA9N1IQEsAbhARQEcALYAjCPigB7AGbiF+SbgA2UMAVySIwOcSiyla6MAAW0fBGLAdeg0fwAaKNYEnBIk9ehcMDB8BRCBXCNPcGhzeQCoOwcnfH1DOSwePgC7KEkBQitHWQooAHdcEE8FKAATCCUBBEsrb0SIJDh8YmEITSrpOEc41TKoAUc2hQR+8r7tesbm2qgRgAZqqAAWCiIpUWBiTN5FHLLvFra7YC6EE1woB3wmwigkaYdKRwgADzBNXBNF5QTQCfLASICabjMRg-4QAwICHAKEITKgSBQADihgASvZgAAFZwAHhgUF+RgQtRM8GQHkJFJ+VJp4iksnwLHQjMpolZGwA-LAmSyTBhsHgiGQYUo5FAAIL0VBMSggRhC+VQcjNET4DhQA1aqA85l8kwARigQvJvOpYowPzW5FVHhwWAIJHITVl8kVzFYaqtCqNOrk+sN5BNoqgACYgzbTXbMA6nQGPD9zc6qK7JZ6ZXK-cqA+rg9qILrwwbIyKzVAAMzxmtJ8WOrMgdOZtNQH4x0guqBuj3S70FxhF1UlzVliuGo1R2s7a1N1kt1P9jNt9O99d1vvZge54cIH0KscsCdBqficth2fkABEuIAogBlAAqxvluPlAFkn2+n1xF8oAAeQAOQAGQATSgABJH9CQgp8-zAgCABFYBA3EoAAVUZN8QO2Y1cVgrCFVxLEcJQt8X3vLgMWgABpCAQGIEClB-QwrAUGkSQAIVwYgIDfGIuSgABvKBqEYmEoAAaxY5QoAEoSRMgWhyBU4SYmk2hl1pRAUCFGTpzlABfagFJAJStLUiBaE4bgAConP1Jy6gRD5gFSFFoSU7ixgSAADJobGeYAgvkliyjUFYYrgTQ4rUOSKBMGL8Dk4FzmsJl-gEJAJmiTEPX2JEjjcqAAAFdFSSRlME7TMQAWhhVwhKQXyxCU216hWaQGreAFiHuakKE0bQ4U0BEDggFYmlcJRcCQewKuq5xYAEPoVhahJGi28Q0kUeQXG4lYEEO2RgTgITaiwcYVEJBQTDaBAFEce8YE2xL708VoTEka7HDABR5s2B4Tp4zIoHctbauNJ6oBa6ZoGUUgKtnDHZw+r7ah+kYEgYxQVASRYmlm1YccwRZcASyYVFexxfFEeh0cxzHH0MW48bUX7bE5-AxEJpSEgh2pWbZrHiVq7n5AeGq0lcInebyLieMwWDah+R5IAKvaTGBnpOpZ6GJfZ-EHBl0okiB5x0nkCV3SlegoZh+W6o1rWWrKGwxEe56THvKX9B+rx-eVg2JlRJWEjdu2PHF03yh9+Gw45i3fraNoEgkGQ5SU2O2tMBoLGV62UgVjI3O4DhCdCuQJn4hq7I8T79p6sU-f0zBA+cH6AB8oA5m4Bf7wfzeAe8S2Y1j2M46weOIRvVNEo0rJspuYnoNxKxTrvsa20ee+lqAB6HrmT7HgkfvQffvu32cPa7jBO-bweg8kQ-x5+oUc45EMb3wGOa8M5DRiRfomVkt9cZBlsjpVuiVaA700hvSA1B4G1D0q-OkSAd5CnAdGM+I8gz4mHggOyS9GoQDQTjWgTAkG71fkfYOQZ3520XrA1B6DaHUA9ogu8DCIEBy-kGHEwBx7vwoXZahW1aAeA9nQ-hoZ5AnCQANb2choCdxem9RQzRo42CIkgbi+UVqKIAWwKAKi1FhWgBwqhXDxgmAZqUJQhlOqrB5sjfR0AjEg2Wv4KwkR2gAEc4ACFyA8VxyBOpcFifNOQi1lr1SEhJHee1EranZHITgs5zAKAwLgTJud3CmHIE8F49ByDSAUAoKalAcmGn6vgApRSOQeGkGU7yLwPBIAFG2Sppgal1IQJwMyXAkBDRMC+OA0hxiSHhIiQ4yToDiTSTjL0CAwoNy0h4e86TcZiXNA0g0eSWkwi2cAChuy8n3l2e-W5UA1hMHaRsi5VzB43Lub3Dw5omADLruFd5eyakPMIQge8LBVkS2uLcTw+A4AQGOVAMZs4mlnIBdshquymmgvuR4J5OYsDW1efXS5OzB44t2V-H5fySWAvJfeSll9SEQtSdC-mgt4WIp3mMsZWRygCHGhSfAoR5DQn2QEoJBBoDONJssXRpgBoTMEsQGuMQ4JgQAGryggrBNClp0AYrJVij5EBBW412egiFjk+CEEMCiBArwC7GA8GXN2HgeYwoFkVPmoTwlqsxLBLVOq9VxkNZs0lQL9m4u+VAX5HAgA) where I define `inherit` as a type alias where the arguments could be gained automatically from the context of where it is used.
This would also support being used in method parameters and return types which would be equivalent to using `Parameters` and `ReturnType` where appropriate.  For example each of these 3 declarations would be equivelent to the following comment
```typescript
class WithInherit extends Base {
    a: inherit; 
    // a: Base["a"]
    b: Readonly<inherit>; // note that we can also compose it with other types
    // b: Readonly<Base["b"]>
    foo(param: inherit): inherit {}
    // foo(param: Parameters<Base["foo"]>[0]): ReturnType<Base["foo"]>{}
}
```
This would also address #2000 with additional capability, if all parameters and return type use `inherit` it will ensure the call signature exactly matches the super class. except without forcing redefining it and allowing extensions like `Readonly<inherit>` shown above or `"fly" | inherit` shown below.

## Use Cases and Examples

### Composition
The proposed keyword would not be required to use alone but could be used like any other type alias. This means that further additions to the original type can be done such as `Partial<inherit>` or similar. Consider this example where we want to override a method `doAction` to accept additional kinds of parameters:
```typescript
class FlyingRobot extends Robot {
    doAction(action: inherit | "fly"){
        // type of input is either "fly" or something the base class supports
        if(action == "fly"){
            // support our case
            return this.fly()
        } else {
            // any other value must be valid to base class since we used inherit.
            return super.doAction(action);
        }
    }
    fly(){}
}
```
This allows us to support an obvious variation of the type defined by the base class and can be easily understood and written without even looking at the original declaration of `Robot[“doAction”]`.

### Interfaces and Multiple Implementations

In the event that a class implements several interfaces, `inherit` will look up fields on an intersection of the base class (if present) and all implemented interfaces:

```typescript
class Foo extends Base implements A, B {
    a: inherit; // resolves to (Base & A & B)["a"]
}
```
For cases where multiple interfaces would define the same method or field `inherit` would resolve to the intersection of all necessary values, or in the case of method overrides resolve only to the last method to remain consistent with `Parameters` and similar constructs. 

### Constraints, Valid and Invalid Uses.

The `inherit` keyword only makes sense inside a class that either extends another class and/or implements at least one interface. If there is no base class then an error should be raised. As well the `inherit` keyword would only be applicable in one of the following positions:
- Instance field
- Getter return value
- Setter parameter
- Method parameter
- Method rest parameter
- Method return value

For parameters and return types, if the corresponding field on the base class is not a function then a compile error should be thrown. Either with a very similar message to the one thrown by `Parameters<0>` or one more specific like “cannot inherit parameter when super field “foo” is not a function”.

For rest parameters, `inherit` should be equivalent to a `extends / infer` statement with the same number of other parameters as specified, with all other types set to `any` for the inference. So if the function is written like `foo(a: number, b: string, …rest: inherit)` the inherit would resolve like this:
`Base[“foo”] extends (a:any, b:any, ...rest: infer T)=>any ? T : never`. And the `never` there would never be used since if `Base[“foo”]` is not a function then a compile error is thrown. Any other case even where `Base[“foo”]` takes only 1 parameter will still give valid results for the rest parameter.

Note that for fields initialized to arrow functions, it is not valid to use `inherit` in the parameters or return type of the arrow function. Instead the full field can use `inherit` then the parameters will be inferred using normal means: [Playground Link](https://www.typescriptlang.org/play/index.html#code/JYOwLgpgTgZghgYwgAgEJwM4oN4ChkHIwD2xAFHAFzIZhSgDmANMgEbUgCuAtq9AJTUAbsWAATANy4AvrgD0c5GAAWwDMjXIxEGKAhiaxJcrhhjKAA4AbOAE8GUYpxAGA7sCtXkCYtwseUUGQAZgA6AHZcMFsLQJBlaGAzAF5kCmpaehBmNg4ePih+ZGSAPmQRcSlcBBsMdQBRAA84PytA1ohuCHB1dCxkPEJkBWQ4UZc2ZASoFBMhFBUFmP1RzjBfU2AEOE9bUbrgBhAV1kwV4hBzJWXkBmB5kHxCEmJqUGmk4rS4FlYi0oG0ik0iAA)
```typescript
class Example implements Base {
    // a and b here are automatically typed when `inherit` resolves to a valid function type. this is nothing new.
    foo: inherit = (a, b) => {};
}
```

### Cases that don’t work

Methods with several overloads and methods with generics are 2 cases where the currently existing `Parameters` and similar construct cannot fully capture the information. This proposal would suggest that no additional work be done to let `inherit` do any extra work in these cases but does recognize that that would be possible in the future.  This means that if a method has a generic the `inherit` keyword will only use the constraint without preserving the generic. Similarly when a method has several overloads `inherit` will only use the type specified in the last overload which without specifying the other necessary call signatures is not valid.

## Checklist

My suggestion meets these guidelines:

* [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code `*`
* [x] This wouldn't change the runtime behavior of existing JavaScript code
* [x] This could be implemented without emitting different JS based on the types of the expressions
* [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).

`*` in order to not break any existing code that may use a type alias called `inherit`, this would need to allow the keyword to be shadowed similar to other built in names.