#Narrowing down the type of a decorator `target`

1 messages · Page 1 of 1 (latest)

celest stag
#

So, a fun one.

Let's say that I have a decorator

export const analyze = (target, key, descriptor) => {
  console.log('implementation');
}

which is used so

export class AnalyzableService {

  constructor(private readonly requiredKey: string, private readonly optionalValue: boolean) {}

  @analyze
  async method() {}
}

is there a sane way to tell TS that the target for this decorator can only be class with a constructor where one of the arguments is a string?

ancient widgetBOT
#
ascor8522#0

Preview:```ts
// @target: esnext
// @experimentalDecorators: true

export function analyze<T extends { new(key: string, ...args: any[]): U }, U>(target: InstanceType<T>, key: keyof U & string, descriptor: PropertyDescriptor) {
console.log('implementation');
}

export class AnalyzableService {
...```

granite cave
#

I don't think it's possible to enforce the constraints on the decorator tho

#

if you change the type key: string to something else, it won't throw an error

#

@celest stag

celest stag
#

right, that was my guess as well. what about creating a record-type where at least one property is of a specific type (regardless of its name)

granite cave
#

I don't think it would help either, it's about the exact same as specifying the instance type using a class

#

only the final shape matters

#

and in your case, the constraint is on the constructor

celest stag
#

but this technically works. if you change the type of foo in the constuctor to number then it starts bitching.

ancient widgetBOT
#
r_rschach#0

Preview:```ts
// @target: esnext
// @experimentalDecorators: true

type F = InstanceType<{ new(key: string, ...args: any[]): any }>;

export function analyze<T extends { foo: string }, U>(target: T, key: keyof U & string, descriptor: PropertyDescriptor) {
console.log('implementation');
...```

celest stag
#

so if there's a way to get rid of the specific key value and just say "object that contains one field with this type"

#

though i guess then i'm stuck with that prop being public :/

granite cave
#

right, only public attributes can be extracted/are exposed and thus checked