javascript - Typescript: Nesporazum oko duck typinga


Učim TypeScript čitajući priručnike i dokumentaciju. I samo me zanima kako TypeScript Duck Typing funkcionira.

Na primjer, ovaj kod daje Type error (koristeći službeni Typescript Playground)

interface Point {
    x: number;
    y: number;
}

const p: Point = {
    x: 1,
    y: 2,
    z: 3
}

function printPoint(p: Point) {
    console.log(p.x + p.y);
}

printPoint(p);

ali ovaj kod ne daje Type error

interface Point {
    x: number;
    y: number;
}

const p = {
    x: 1,
    y: 2,
    z: 3
}

function printPoint(p: Point) {
    console.log(p.x + p.y);
}

printPoint(p);

Mislim da je problem vezan uz Typescript-ovo Duck Typing, ali nisam mogao razumjeti zašto sustav tipova argumenata i sustav tipova konstante funkcioniraju na različit način.

jesam li pogrešno shvatio Duck Typing? const p sadrži x, y, pa mislim da bi const p: Point trebao raditi

Odgovor #1

Typescript nameće različite razine strogoće ovisno o tome što radite. Kada kreirate varijablu s eksplicitnim tipom, typescript je vrlo strog u vezi s tim što mora biti prisutno, ne dopuštajući dodatna svojstva. Dodatno svojstvo vjerojatno je greška u vašem kodu, budući da kreirate vrijednost a zatim odmah dodjeljujete tip, što tu vrijednost čini nedostupnom. Dakle, dodatna strogoća pomaže vam uhvatiti takve greške.

Kada pokušate dodijeliti jednu varijablu drugoj, uključujući prosljeđivanje varijable u funkciju, TypeScript provodi popustljiviju provjeru. Dvije varijable samo trebaju biti kompatibilne jedna s drugom, što otprilike znači da moraju imati barem navedena svojstva s ispravnim tipovima, ali je u redu ako imaju i dodatna svojstva. Ova popustljivija razina provjere dio je načina na koji TypeScript podržava podtipove i podklase. Trebali biste moći proslijediti podklasu tamo gdje se traži osnovna klasa (princip Liskovljeve supstitucije), ali podklasa će često imati dodatna svojstva.

Pogledajte ovaj link za više informacija o kompatibilnosti tipova: https://www.typescriptlang.org/docs/handbook/type-compatibility.html

Odgovor #2

Prvi kod je prikazao TypeError jer sučelje Point nema član z. Drugi kod nije imao pogrešku tipa, jer u funkciji sve svojstva na koja se referencira (x i y) postoje u tipu Point. To je zbog Duck Typinga i činjenice da se prihvaća kao Point ili ne, jer član z nije referenciran. Unutar funkcije, ako pokušate koristiti p.z, dobit ćete pogrešku tipa.