typescript - Er det mulig å få en funksjon til å akseptere klasseinstanser, men ikke akseptere vanlige objekter?


Jeg vil gjerne skrive en funksjon som tar klasseinstanser som parameter, men ikke tillater vanlige, anonymt typede objekter.

For eksempel:

class Dog {
    constructor(name: string, breed: "husky" | "boxer") {
        this.name = name;
        this.breed = breed;
    }
    name: string;
    breed: "husky" | "boxer";
}

class Cat {
    constructor(name: string, breed: "siamese" | "persian") {
        this.name = name;
        this.breed = breed;
    }
    name: string;
    breed: "siamese" | "persian";
}

function pat(pet: NoPlainObjects) {
    document.write(pet.constructor.name);
}

pat(new Dog('Fido', 'boxer')); //works
pat(new Cat('Spot', 'persian')); //works

pat({name: 'snuffaluffagus'}); //compile error

Svar #1

Er det mulig å la en funksjon akseptere klasseinstanser, men ikke vanlige objekter?

Det er ikke mulig for øyeblikket, fordi TypeScript bruker strukturell sub-typing. Det betyr at et objekt opprettet med en klassekonstruktør er kompatibelt med en vanlig JavaScript-objektliteral når begge har kompatible egenskaper.

Her er hva dokumentasjonen sier om typekompatibilitet:

Den grunnleggende regelen for TypeScripts strukturelle typesystem er at x er kompatibel med y hvis y har minst de samme medlemmene som x. For å sjekke om y kan tildeles til x, sjekker kompilatoren hver egenskap til x for å finne en tilsvarende kompatibel egenskap i y... Den samme regelen for tildeling brukes når man sjekker argumenter ved funksjonskall. [uthevet lagt til]

Spørsmålet ditt reiser et spørsmål: hvorfor skulle du ønske at en funksjon skulle akseptere klasseinstanser og avvise vanlige gamle JavaScript-objekter?

Svar #2

Du kan bruke pipe-tegnet for å tillate forskjellige typer som argument for funksjonen din.

function pat(pet: Cat | Dog) {
    document.write(pet.name);
}

Relaterte artikler