TypeScript Version: ^3.7
Search Terms:
declare decorator decorated class property
Code
function baz(_target: Object, _key: string) {};
class Foo {
@baz declare bar: string;
}
Expected behavior:
Error due to decorating ambient context.
Actual behavior:
No error, decorated property is emitted (exact same output as without declare).
Playground Link:
https://www.typescriptlang.org/play/?experimentalDecorators=true&ssl=6&ssc=2&pln=2&pc=1#code/FAMwrgdgxgLglgewgAgEYEMBeAKA+jdAJwHMBTGALmQHlUArU2AGmVwGtSBPKgZxkLgRiASmQBvAL4BuYMCgAbdDx7IAYggTjgyZAAEMmZABNGiwqTRFe-QcRkSgA
Related Issues:
Is this an error or a feature? I think it's useful since I'm using this pattern for dependency injection.
````
class A {
@Inject('AnyNamespace.AnyInterface')
declare private Foo: AnyNamespace.AnyInterface;
method() {
this.Foo.blabla... // <-- this.Foo is type-safe.
}
}
```
DI module will inject to the propertyFoofrom decorator, so the assignment could be omitted. However, since I enabledstrictPropertyInitialization: true, property declaration without initialization will result in an error. So thedeclare` keyword is needed.
If it turns to be an error, the injection to property have to be written as
@Inject('AnyNamespace.AnyInterface')
private Foo: AnyNamespace.AnyInterface = undefined as any;
What about using definite?
@Inject('AnyNamespace.AnyInterface')
private Foo!: AnyNamespace.AnyInterface;
What about using definite?
@Inject('AnyNamespace.AnyInterface') private Foo!: AnyNamespace.AnyInterface;
Sorry for the late reply, but declare foo: any and foo!: any may have different behavior: The latter will overwrite its value when useDefineForClassFields: true is set.
declare function SomeDecorator(...args: any): any;
class A {
foo: string = 'foo';
}
class B extends A {
@SomeDecorator
declare foo: string;
}
class C extends A {
@SomeDecorator
foo!: string; // <- warning here.
// Property 'foo' will overwrite the base property in 'A'. If this is intentional, add an initializer.
// Otherwise, add a 'declare' modifier or remove the redundant declaration.(2612)
}
Sometimes I don't need to overwrite the value, only want to add some behavior by using a decorator.
There will be no way to do it if decorating a declared property becomes an error.
This is actually an intended behavior, and one of the reasons declare exists. If you are compiling targeting native fields, or with --useDefineForClassFields, redeclaring a field in a subclass just to decorate it would _actually overwrite the field_, as @whzx5byb mentions above. We allow you to decorate a declare field as that is the only way to decorate the field on a subclass without overwriting it.
Thanks, @rbuckton! TBH I should have closed this months ago. Decorated declare properties is a pattern I now use regularly. I even wrote a blog post about it! 😆
Most helpful comment
What about using definite?