Repository: TypeScript
Issue: `override` modifier should able to be used with `declare` modifier
Labels: Suggestion,In Discussion

# Suggestion
<!--
  Please fill in each section completely. Thank you!
-->

## 🔍 Search Terms
useDefineForClassFields 
override declare
'override' modifier cannot be used with 'declare' modifier. ts(1243)
Property 'a' will overwrite the base property in 'Cls'. If this is intentional, add an initializer. Otherwise, add a 'declare' modifier or remove the redundant declaration.(2612)

## ✅ Viability Checklist

<!--
   Suggestions that don't meet all these criteria are very, very unlikely to be accepted.
   We always recommend reviewing the TypeScript design goals before investing time writing
   a proposal for ideas outside the scope of the project.
-->
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, new syntax sugar for JS, etc.)
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).


## ⭐ Suggestion
When declaring class fields:

The `override` modifier should be able to be used with `declare` modifier.

Have `!` work in the place of `declare` OR:
Remove this error if `!` or `override` is specifically given: Property 'a' will overwrite the base property in 'Cls'. If this is intentional, add an initializer. Otherwise, add a 'declare' modifier or remove the redundant declaration.(2612)

## 📃 Motivating Example

Given a decorator `Prop()` that somehow declares some metadata on the class field, 
that would later be used in some other technical components like Database ORMs or Validators, etc.

Consider this example, before `useDefineForClassFields` set to `true`:
```typescript
interface Animal {
  animalStuff: any;
}
interface Dog extends Animal {
  dogStuff: any;
}

class AnimalHouse {
  internalProp: number;

  @Prop({
    default: {
      animalStuff: 'food',
    }
  })
  resident: Animal;

  @Prop({
    default: 'foo'
  })
  someOtherProp: string;

  constructor(animal: Animal) {
    this.resident = animal;
  }
}

class DogHouse extends AnimalHouse {
  @Prop({
    default: {
      animalStuff: 'food',
      dogStuff: 'dog food',
    }
  })
  override resident: Dog;
}
```

Note that the `DogHouse` is defined quite straightforward and expected in a general sense.

Now after `useDefineForClassFields` set to `true`, the current way of specifying the `DogHouse` becomes:
```typescript
class DogHouse extends AnimalHouse {
  @Prop({
    default: {
      animalStuff: 'food',
      dogStuff: 'dog food',
    }
  })
  declare resident: Dog;
}
```
It doesn't look too bad, but things can get more complicated:


```typescript
class DogHouse extends AnimalHouse {
  override internalProp: 42;

  @Prop({
    default: {
      animalStuff: 'food',
      dogStuff: 'dog food',
    }
  })
  declare resident: Dog;
  
  @Prop({
    default: 'foo'
  })
  override someOtherProp: string = 'foo';
  
  @Prop({
    default: 'foo'
  })
  someOtherProp2: string;
}
```

Now it sucks. 

The consistency and readability from using `override` is completely screwed up by `declare`.

At least the `override` should be allowed to be used with `declare` to make it suck a little less:

```typescript
class DogHouse extends AnimalHouse {
  override internalProp: 42;

  @Prop({
    default: {
      animalStuff: 'food',
      dogStuff: 'dog food',
    }
  })
  declare override resident: Dog;

  @Prop({
    default: 'foo'
  })
  override someOtherProp: string = 'foo';
  
  @Prop({
    default: 'foo'
  })
  someOtherProp2: string;
}
```

The best case however, is to have `!` work in the place of `declare`:

```typescript
class DogHouse extends AnimalHouse {
  override internalProp: 42;

  @Prop({
    default: {
      animalStuff: 'food',
      dogStuff: 'dog food',
    }
  })
  override resident!: Dog; // No declaration emit
  
  @Prop({
    default: 'bar'
  })
  override someOtherProp: string; // With declaration emit
  
  @Prop({
    default: 'foo'
  })
  someOtherProp2: string;
}
```

## 💻 Use Cases

As example suggested.

The code readability degradation from `declare` is unacceptable.

I am using typescript with `useDefineForClassFields` set to `off` now.


Please consider my suggestion..

<!--
  What do you want to use this for?
  What shortcomings exist with current approaches?
  What workarounds are you using in the meantime?
-->