microsoft / microsoft/TypeScript
Suggestion: ClassMethodDecoratorContext's name property could pick up Value["name"]
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.4k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 117
Description
lib Update Request
Configuration Check
My compilation target is ESNext and my lib is the default.
Missing / Incorrect Definition
interface ClassMethodDecoratorContext<
This = unknown,
Value extends (this: This, ...args: any) => any = (this: This, ...args: any) => any,
> {
// ...
/** The name of the decorated class element. */
readonly name: string | symbol;
// ...
We could change the name field to: readonly name: Value extends { name: string } ? Value["name"] : (string | symbol);. Most of the time, Value["name"] is just string, so this would be a non-breaking change (if slightly less intuitive).
However, if I were to augment my method type definitions to have a name property, TypeScript could pick up on it:
Sample Code
export type NumberStringType = {
repeatForward(s: string, n: number): string;
repeatBack(n: number, s: string): string;
};
type NST_RF_raw = NumberStringType["repeatForward"]["name"]
// ^? type NST_RF_raw = string
type MethodsOnlyType = {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
[key: string | number | symbol]: (...args: any[]) => any
}
type NamedMethodsOnlyType<T extends MethodsOnlyType> = {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
[Key in keyof T]: T[Key] & { name: Key }
}
type NST_RF_named = NamedMethodsOnlyType<NumberStringType>["repeatForward"]["name"];
// ^? type NST_RF_named = "repeatForward"
type DefaultInferredName = ClassMethodDecoratorContext<
// ^? type DefaultInferredName = string | symbol
NumberStringType, NamedMethodsOnlyType<NumberStringType>["repeatForward"]
>["name"];
interface ClassMethodDecoratorContext_Named<
This = unknown,
Value extends (this: This, ...args: any) => any = (this: This, ...args: any) => any,
> {
readonly name: Value extends { name: string } ? Value["name"] : (string | symbol);
}
type DirectName = ClassMethodDecoratorContext_Named<
// ^? type Directname = "repeatForward"
NumberStringType, NamedMethodsOnlyType<NumberStringType>["repeatForward"]
>["name"];
type InferredName = ClassMethodDecoratorContext_Named<
// ^? type InferredName = string
NumberStringType, NumberStringType["repeatForward"]
>["name"];
Motivation
I've been experimenting with method decorators for about a week now, to implement some aspect-oriented programming (or at least, my understanding of it). One facet I haven't yet cracked is removing the need for the method name on a decorator:
class NST_Class extends NumberStringClass {
@precondition<"repeatForward">(callForwardPre)
repeatForward(s: string, n: number): string {
return super.repeatForward(s, n);
}
}
Since the context has a name field of string | symbol type, I can't infer the name from that... I think.
I am perfectly willing to be wrong and have this whole ticket closed as invalid!
Documentation Link
The ECMAScript 2023 specification for Function.name says I'm possibly wrong here: it specifies the name field must be a string (specifically, "not a symbol"). This could be just a specification bug with the introduction of symbol keys, but I am not ready to assert that at this time.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the ClassMethodDecoratorContext definition and compare the proposed conditional name type with the ECMAScript Function.name specification. Use the linked Playground to verify the inferred results for the named and unnamed cases. Done means resolving whether the proposed lib-definition change is valid under the specification.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100