Hvordan man korrekt bruger funktions konstruktionssignaturer i TypeScript


Jeg læser TS-dokumentation, og når jeg læser More on Functions, forstår jeg ikke koden nedenfor, og hvordan man bruger den i faktisk udvikling. Er der nogle eksempler?

interface CallOrConstruct {
  new (s: string): Date;
  (n?: number): number;
}

Svar #1

Hvad du ser her er et enkelt objekt, der har forskellig adfærd afhængigt af, om du kalder det med new. Dette er noget, Javascript er i stand til at gøre, men det kan føre til forvirrende kode; du vil sandsynligvis kun se den slags signatur meget sjældent, eller når du tilpasser et meget gammelt eller fleksibelt Javascript-bibliotek til brug i Typescript.

(Teknisk set behøver adfærden ikke at være forskellig: Fornuftige objekter kan muligvis kaldes med eller uden new med samme overordnede adfærd, og ville kræve både call og construct signaturer. Dog er denne form for bevidst fleksibilitet stadig usædvanlig. Tak @kaya3!)


Dit uddrag vises i Flere om funktioner under teksten:

Nogle objekter, som JavaScripts Date-objekt, kan kaldes med eller uden new. Du kan kombinere call- og construct-signaturer i samme type arbitrært:

Dette er en reference til det indbyggede Date-objekt, som har denne tekst på MDN:

Date()

Når den kaldes som en funktion, returnerer den en strengrepræsentation af den aktuelle dato og tid, præcis som new Date().toString() gør.

new Date()

Når den kaldes som en konstruktør, returnerer den et nyt Date-objekt.

console.log(typeof Date())      // string
console.log(typeof new Date())  // object

Som nævnt ovenfor er det meget sjældent, at et enkelt Funktionsobjekt vil tjene begge formål: Man vil normalt se en funktion/klasse blive bevidst kaldt som den ene eller den anden, men ikke begge. Dog, fordi det er muligt at gøre i Javascript (og endda gjort i indbyggede objekter), er det vigtigt for TypeScript at kunne repræsentere et objekt, der fungerer i begge opkaldsstilarter.

interface CallOrConstruct {
  new (s: string): Date;      // construct
  (n?: number): number;       // call
}

// construct
let object: Date = new CallOrConstruct("optional string s");

// call
let myNumber: number = CallOrConstruct(/* n= */ 42);

Du vil sandsynligvis aldrig få brug for at skrive et interface som dette, især hvis du bruger class og constructor til klasser og function (eller andre normale funktionsdeklarationer) til dine funktioner. Du vil kun have brug for at gøre det, hvis du prøver at erklære typer, som TypeScript ikke forstår (som i en .d.ts TypeScript-deklarationsfil til et eksternt Javascript-bibliotek) eller hvis du prøver at skrive et smart og forvirrende TypeScript-objekt, der kan bruges på begge måder. Personligt har jeg ikke haft nogen grund til at skrive min egen deklaration som denne, selvom jeg har læst nogle i biblioteker og deres typer.

Relaterede artikler