`override` modifier should able to be used with `declare` modifier
See original GitHub issueSuggestion
š 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
My suggestion meets these guidelines:
- This wouldnāt be a breaking change in existing TypeScript/JavaScript code
- This wouldnāt change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isnāt a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This feature would agree with the rest of TypeScriptās 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
:
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:
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:
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:
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
:
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ā¦
Issue Analytics
- State:
- Created 10 months ago
- Comments:8
Top GitHub Comments
Iāve put it in another way, hopefully it can convenience you more. https://github.com/microsoft/TypeScript/issues/51536
@fatcerberus Apologies If my words are too offensive. Iām not very good at English after all. I just wanted to express my feeling on this issue and the direction it is developing. Now I believe you have acknowledged my frustration. I hope the user frustration still means something to TS devs. Maybe Iāll start a new issue and rephrase all about this after further discussion.
Itās not about the new ES Class define behaviour, not on their part. This is exactly a TypeScript issue.
According to your own reply here, you are well aware of no matter what TS do, the eventual behaviour will change because of the underlying runtime. Then itās ok to treat it transparently and not throw errors on this:
At least it should have an option to disable this error.
Property 'resident' will overwrite the base property in 'AnimalHouse'. If this is intentional, add an initializer. Otherwise, add a 'declare' modifier or remove the redundant declaration.(2612)
FYI the decorator is working as expected. I authored those decorators. Itās using the
metadata registering
approach. Itās not about the code not working; it works. Itās about TypeScript not allowing this formerly-valid clear, precise way of writing code anymore, and proposes another much less favourable approach, known asdeclare
.