Infer method name for parameter decorator
See original GitHub issueTypeScript Version: 3.3.3 Tried with @next (3.4.0-dev.201xxxxx) ? NO
Search Terms: type:issues infer method name parameter decorator
Code
declare function Method():
{
(t: any, m: 'method'): void;
}
declare function Parameter():
{
(t: any, m: 'method', i: number): void;
}
class Play
{
@Method() // err
public another_method ( @Parameter() /* NO ERROR */ test: number ): void
{
throw new Error('Not yet implemented');
}
@Method()
public method ( @Parameter() test: number ): void
{
throw new Error('Not yet implemented');
}
}
Expected behavior: @Parameter()
should error just as @Method()
when applied to another_method()
because the m
parameter is typed "method"
(which should reduced the set of method). i.e method name should be enforced.
Actual behavior: No error
Playground Link: https://typescript-play.js.org
Use case :
I crafted a type that filters method names with the nth
parameters iff that parameters is of the given type T
.
See KeysToTypedNthParameter
definition here
let hash = {
a( _0: string, _1: string ) {},
b( _0: string, _1: number ) {},
c( _0: number, _1: number ) {},
d( _0: number, _1: string ) {},
}
let string_0: KeysToTypedNthParameter<0, string, typeof hash>; // "a" | "b"
let string_1: KeysToTypedNthParameter<1, string, typeof hash>; // "a" | "d"
let number_0: KeysToTypedNthParameter<0, number, typeof hash>; // "c" | "d"
let number_1: KeysToTypedNthParameter<1, number, typeof hash>; // "c" | "d"
Later, I used that type to infer method name for my parameter decorator - @Inject
- in the excerpt below, I marked the ONLY line that should error and why (but both lines actually error)
class Test
{
public blatantly!: boolean;
}
class Play
{
public method(
@Inject({ type: Test })
@Inject({ type: Number }) // err (construtor mismatch instance type)
test: Test,
): void
{
throw new Error( 'Not yet implemented' );
}
}
Play;
Here is @Inject
decorator definition and complete code -
const Inject: InjectLike = void 0 as unknown as InjectLike;
interface InjectLike
{
<
C extends ConstructorLike,
>
({}: { type: C }): {
<
// FIXME : not enough to infer the method name - see ./__playground.ts#
M extends ( T extends ConstructorLike ? never : KeysToTypedNthParameter<I, InstanceType<C>, T> ),
I extends number,
T,
>
( target: T, member: M, index: I ): void;
};
}
Issue Analytics
- State:
- Created 5 years ago
- Reactions:4
- Comments:7 (3 by maintainers)
Top GitHub Comments
Hi any movement on this? Now that the 3.4 release rush is over can I submit a PR with the code I have for this (@DanielRosenwasser , @RyanCavanaugh, @rbuckton) ?
@rbuckton @RyanCavanaugh
Just as an experiment I made the changes we (me an @SalathielGenese) think are required, you can see them here
These changes do the following:
parameterIndex
the number literal type is used instead ofnumber
propertyKey
the literal type is used instead orundefined
if the decorator is used on a constructor parametertarget
the actual type of the target is passed in, like it is for method decorators.Uses cases enabled:
Problems:
propertyKey
can be typedundefined
thelib
version ofParameterDecorator
is not really correct anymore,propertyKey
should bestring | symbol | undefined
propertyKey
will be typed asundefined
in this case). I would argue this is correct behavior, sinceundefined
was always a possible value for thepropertyKey
parameter.