ProgrammatieFrontend/Fullstack ontwikkelaar

Hoe werkt de typering van class constructors in TypeScript en welke problemen kunnen optreden bij overerving?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Geschiedenis van de vraag

Aanvankelijk had JavaScript geen strikte typering voor klassen en hun constructors, wat leidde tot runtime-fouten. TypeScript heeft een typesysteem toegevoegd voor veiliger programmeren en ondersteunt de typering van constructors met overerving, wat belangrijk is voor de ontwikkeling van grote toepassingen.

Probleem

De typering van constructors in TypeScript vereist gelijktijdige overweging van de handtekening van de constructor, het type van het gemaakte exemplaar en de kenmerken van overerving. Problemen ontstaan wanneer de handtekeningen van de constructors in de basis- en afgeleide klasse niet overeenkomen, of wanneer alleen de teruggegeven waarde getypeerd is en niet de invoerparameters van de constructor.

Oplossing

In TypeScript kunnen constructors expliciet worden getypeerd via speciale handtekeningen, met behulp van de expressie new (...args: any[]) => T. Bij overerving is het belangrijk om de handtekeningen consistent te houden en de basisclassen correct uit te breiden.

Codevoorbeeld:

class Animal { constructor(public name: string) {} } class Dog extends Animal { constructor(name: string, public breed: string) { super(name); } } // Type van de constructor function createInstance<T>(C: new (...args: any[]) => T, ...args: any[]): T { return new C(...args); } const dog = createInstance(Dog, 'Rex', 'Labrador');

Belangrijke kenmerken:

  • De handtekening van de constructor is een aparte entiteit, gedeclareerd met new
  • Handhaving van de compatibiliteit van parameters tussen de basis- en afgeleide constructor
  • Mogelijkheid tot universele creatie van exemplaren via getypeerde constructors

Vragen met een addertje onder het gras.

Kan ik meerdere constructors in een klasse declareren, zoals in Java of C#?

Nee, TypeScript ondersteunt geen meerdere constructors. Om overbelasting te imiteren, worden handtekeningoverloadingen gebruikt met één implementatie. De juiste aanpak:

class Example { constructor(x: string); constructor(x: number); constructor(x: number | string) { // Eén implementatie } }

Kan ik alleen het teruggegeven type van de constructor typeren, en de parameters negeren?

Nee, de handtekening van de constructor omvat noodzakelijkerwijs parameters. Voorbeeld van juiste typering:

interface Constructable<T> { new (...args: any[]): T; }

Wat gebeurt er als ik in de afgeleide klasse een constructor declareer zonder super aan te roepen?

Er zal een compilatiefout optreden: de constructor van de afgeleide klasse moet super aanroepen voordat hij naar this verwijst.

Typische fouten en anti-patronen

  • Niet-overeenkomende parameters van de constructor tussen basis- en afgeleide klasse
  • Geen aanroep van super in de constructor van de afgeleide klasse
  • Onjuiste typering van de constructor bij abstractie via fabrieken

Voorbeeld uit het leven

Negatieve case

In het project werd een basis klasse Animal met een constructor (name) gebruikt, en in de afgeleide klasse Dog werd (name, breed) toegevoegd, maar de handtekening werd niet correct uitgebreid.

Voordelen:

  • Documenteert nieuwe parameters

Nadelen:

  • Schending van de compatibiliteit bij het maken van exemplaren via universele fabrieken, fouten tijdens de compilatie

Positieve case

Het type van de constructor is apart opgenomen, de fabriek createInstance is geparametriseerd via CorrectConstructable<T>, de handtekeningen zijn gerespecteerd.

Voordelen:

  • Typeveiligheid, voorspelbaar gedrag
  • Makkelijk om universele functies te schrijven

Nadelen:

  • Vereist grondigere uitwerking van typering