#How do I type / overload a Stage1 Decorator?

20 messages · Page 1 of 1 (latest)

naive sparrow
#

experimentalDecorators is "Stage2" ... which is really close to the Stage1 decorators.

The issue I'm having is that the types for property decorators have the third argument as optional (?:), even though it's always present

#

is there some trick I can do (maybe with nevers?) to get my overload to work?

dreamy badger
#

experimentalDecorators is "Stage2" ... which is really close to the Stage1 decorators.
A little confused by this - pretty sure the "experimental decorators" are a non-standard TS implementation that isn't 'stage anything'.

#

And the non-experimental decorators are stage 3

naive sparrow
#

right, my actual project is not using Stage 3 decorators, nor Stage 2, but experimentalDecorators provides types for Stage 2 (the playground even says this)

#

but that's besides the point

#

I'm mostly just trying to make an overload work with an optional third argument:

function foo(...args: Parameters<typeof fooDecorator> | Parameters<typeof fooNonDecorator>) {
    // decorators have 3 args, not 2 -- descriptor is always present
    if (args.length === 3) {
        return fooDecorator(...args) as void;
    }

    if (args.length === 2) {
        if (typeof args[1] !== 'string' && typeof args[1] !== 'symbol') {
            return fooNonDecorator(args[0], args[1]);
        }
    }

    throw new Error('incorrect arity');
}

function fooNonDecorator<Value>(context: object, value: Value): Value {
    console.log(context);
    return value;
}
function fooDecorator(prototype: object, key: string | symbol, descriptor?: {}): void {
    return descriptor as unknown as void; // no-op, TS types are wrong for Stage 1 Decorators
}
#

hmm, TS' PropertyDecorator type is wrong thinkies

#

I was thinking I could override it:

declare global {
  interface PropertyDecorator {
    (target: any, key: string | symbol, descriptor: PropertyDescriptor): void;
  }
}

but TS is saying "duplicate identifier"

#

which like.. fair

#

reason why I'm trying to override the type now is because I found out TS only considers a function a decorator based on the first two arguments, which is why I ha previousyl a ?: for descriptor

#

I have this so far -- in my first snippet, I forgot to actually overload the function

#

ooo, I may have done it

#

love that type guards let me lie to the type system. lol

#

ehh... maybe not. Just started trying to test with expect type

#

Ok, now this matches the situation I have locally

lofty martenBOT
#
nullvoxpopuli#0

Preview:```ts
// declare global {
// interface PropertyDecorator {
// (target: any, key: string | symbol, descriptor: PropertyDescriptor): void;
// }
// }

function foo(prototype: object, key: string | symbol, descriptor?: PropertyDescriptor): void;
function foo<Value>(context: ThisType<object>, value: Value, _?: never): Reactive<Value>;
...```

naive sparrow
#

It's just getting worse 😅

lofty martenBOT
#
nullvoxpopuli#0

Preview:```ts
import type {Class, Constructor} from "type-fest"

function foo<Value, K>(
prototype: InstanceType<Class<K>>,
key: string | symbol,
descriptor?: PropertyDescriptor
): void
function foo<Value, K>(
context: ThisType<K>,
value: Value
): Reactive<Value>

type Foo<X> = X extends object ? never : X
...```

naive sparrow
#

anyone have ideas?