microsoft / microsoft/TypeScript

Allow interface merging for DecoratorMetadataObject and parameterization by This

Aperta
#60,997 0 commenti 2 reazioni 1 assegnatario Vedi su GitHub

@rbuckton ci sta già lavorando.

Dal 13/2/2025.

Needs Investigation
Lingua principale
Go
Stelle
111k
Fork
14.3k
Merge medio
1g 19h
PR unite (30g)
117

Descrizione

⚙ Compilation target

ESNext

⚙ Library

ESNext

Missing / Incorrect Definition

Currently DecoratorMetadataObject is defined as a type, however as metadata objects are intended to store values on behalf of user-defined decorators it would be useful to be able to specify more precise types for properties that such decorators add as metadata.

Sample Code

As an example, at current if we do:


const jsonFields = Symbol('jsonFields');

function field<This>(field: undefined, ctx: ClassFieldDecoratorContext<This>) {
    ctx.metadata[jsonFields] ??= [];
    // Object is of type 'unknown'.(2571)
    ctx.metadata[jsonFields].push(ctx.access.get);
}

function toJSON(obj: any) {
    // Get metadata from obj.constructor and process fields here
    // ...
}

class Foo {
    @field
    x: number = 3;
    @field 
    y: number = 4;
}

Then we get a fairly expected Object is of type 'unknown'.(2571) error.

However if allow declaration merging, then we can have better typing:

declare global {
    interface DecoratorMetadataObject {
        [jsonFields]?: Array<(this: object) => any>; 
    }
}

// Define decorator as before

If we further allow the metadata context to be parameterized with This, we can even allow even better typing:

declare global {
    interface DecoratorMetadataObject<This> {
        [jsonFields]?: Array<(this: This) => any>; 
    }
}

// define decorators...

class Foo {
    @field
    x = 3;
}

Foo[Symbol.metadata] // { [key: string]: unknown; [jsonFields]?: Array<(this: Foo) => any> }

This also helps detect conflicts if two libraries try to the use the same string-based decorator field:

// lib1
interface DecoratorMetadataObject {
    meta?: number;
}

function lib1Decorator() { /* ... */ }

// lib2
interface DecoratorMetadataObject {
    // Subsequent property declarations must have the same type.
    // Property 'meta' must be of type 'number | undefined', but here has type 'string | undefined'.(2717)
    meta?: string;
}


function lib2Decorator() { /* ... */ }

(and if TS adds type based metadata, it can give those appropriate types in the metadata object in the same way).

Documentation Link

No response

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.