type-graphql icon indicating copy to clipboard operation
type-graphql copied to clipboard

Decorate constructor arguments with access modifiers

Open cyberprodigy opened this issue 5 years ago • 5 comments

Is your feature request related to a problem? Please describe. We are using extensively cool TypeScript feature which allows parameters from constructor map to class members, Example:

export class User {
  constructor(
    public id: number,
    public username: string,
 ) { }
}

then

let admin = new User(1,'admin');
console.log(admin.id) // prints 1

Describe the solution you'd like I would like to be able to decorate these parameters as well

Describe alternatives you've considered Don't use this TS feature

cyberprodigy avatar Dec 16 '19 11:12 cyberprodigy

For now, @Field() is a MethodAndPropDecorator, so you can't do that.

While it's possible to add support for parameters in constructor, it's an error prone pattern as you can easily missplace the parameter and swap mobilePhone with homePhone, age with balance and others.

If you really want to create a class instance, it's better to accept the anonymous object in constructor and call Object.assign inside of it.

MichalLytek avatar Dec 16 '19 13:12 MichalLytek

it's an error prone pattern

every pattern can be missused, but there are a lot of use cases where object types have very few arguments, or are constructed by a factory or builder pattern.

just to have an example for a valid use case:

@InterfaceType()
abstract class UpdateUserResult {
  public constructor(
    @Field(() => User)
    public readonly user: User,
  ) {}
}

@ObjectType({ implements: UpdateUserResult })
class UpdateUserResultOk extends UpdateUserResult {}

@ObjectType({ implements: UpdateUserResult })
class UpdateUserResultRejected extends UpdateUserResult {
  public constructor(
    user: User,
    @Field(() => String)
    public readonly reason: string,
  ) {
    super(user);
  }
}

backbone87 avatar May 17 '20 14:05 backbone87

Should be fairly easy to implement, moving to 1.x release milestone 👀

MichalLytek avatar May 17 '20 15:05 MichalLytek

this feature is very welcome to easily form up responses in queries mutations etc

ruohki avatar Aug 22 '20 13:08 ruohki

Any progress on this? Quality of Life feature :)

ruohki avatar Mar 14 '21 14:03 ruohki

I've checked and unfortunately this is not possible 😞 https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html#more-accurate-type-checking-for-parameter-decorators-in-constructors-under---experimentaldecorators

When using decorator on constructor argument, it's treated like a function parameter decorator. So we have no propertyKey information, only the parameter index. So we can't make it working easily.

The only solution would be to duplicate the property name in the decorator options:

@ObjectType()
export class User {
  constructor(
    @Field(() => Int, { propertyName: "id" })
    public id: number,
    
    @Field({ propertyName: "username" })
    public username: string,
 ) { }
}

Which makes no sense, it's same duplication like now with defining constructor params apart from the fields definitions.

MichalLytek avatar Jan 10 '24 16:01 MichalLytek