JavaScript til TypeScript: Intellisense og dynamiske medlemmer


Jeg har et JavaScript-objekt som dynamisk tillater medlemmer å bli bundet som tilkomstegenskaper til instanser av objektet:

Kilde

function DynamicObject(obj) {
    for (var prop in obj) {
        Object.defineProperty(this, prop, {
            get: function () { return obj[prop]; },
            set: function (value) { obj[prop] = value; },
            enumerable: true,
            configurable: false
        });
    }
}

Bruk

var obj = new DynamicObject({
    name: "John Smith",
    email: "[email ",
    id: 1
});

Når obj opprettes, blir medlemmene til konstruktørparameteren bundet til obj som aksessoregenskaper. Disse vises i intellisense

Jeg vil gjerne vite om det er mulig å modellere denne typen oppførsel (inkludert å ha intellisense) i TypeScript?

Notater

Når du kjører denne koden i TypeScript, er det ingen intellisense fordi alt er any, så TypeScript vet egentlig ikke hva som foregår.

Svar #1

Du kan ikke. Dette er helt dynamiske egenskaper, lagt til under kjøring, så du kan umulig vite hva de er på kompileringstidspunktet. Jeg vil også hevde at du ikke ønsker å vite hva de er så tidlig; hvis du har begrensninger som må håndheves, bør de bare angis på egen hånd (første eksempel nedenfor).

Hvis koden din avhenger av et sett med tilganger, bør du legge disse direkte inn i grensesnittet eller kontrakten, fordi du vet på forhånd at du forventer dem og bør gjøre det kjent. Du kan bruke valgfrie egenskaper (med tilgangen definert senere) for å gjøre det enklere:

interface HasSomeProps {
  foo: string;
  bar?: string;
}

class DoesTheProps implements HasSomeProps {
  set foo(value) { 
    // ...
  }
}

Hvis du har en mengde konsekvente (eller semi-konsekvente) aksessorer, kan du definere en indekser på typen din slik som:

interface AccessStrings {
  [key: string]: string;
}

Det lar deg ikke begrense nøklene. Hvis du vil det, bør du eksplisitt liste opp egenskapene.

Svar #2

Jeg vil gjerne vite om det er mulig å modellere denne typen oppførsel (inkludert å ha intellisense) i TypeScript?

Ja.

Du kan tilordne en generell kallbare signatur til DynamicObject. Du må deklarere det som en variabel:

var DynamicObject: new <T>(obj: T) => T = function (obj)
{
    for (var prop in obj)
    {
        Object.defineProperty(this, prop, {
            get: function () { return obj[prop]; },
            set: function (value) { obj[prop] = value; },
            enumerable: true,
            configurable: false
        });
    }
} as any;

På denne måten vil IntelliSense behandle verdien som returneres fra new DynamicObject som å ha samme type som verdien som blir sendt inn. Samme egenskapsnavn, samme egenskapstyper. Du vil få full autoutfylling og typesikkerhet.

Direktesendt demo på TypeScript-lekeplass

Hvis du har problemer med å forstå den delen i den første linjen, er det det samme som å skrive følgende:

// Declare type (only exists during compile-time)
var DynamicObject: new <T>(obj: T) => T;

// Assign value (during runtime)
DynamicObject = function (obj)
{
    ...
} as any;

Relaterte artikler