Hvorfor tillater Typescript at `{a: 1, b: 2}` kan tilordnes til typen `{a: any} | {b: any}`?


Vurder denne koden:

let foo: {a: any} | {b: any} = {a: 1, b: 2};

Jeg forventer at TypeScript vil avvise denne koden, siden denne unionstypen betyr enten den første typen eller den andre typen, og at verdien ikke kan tildeles noen av dem, derfor bør typetesten avvise den. Men faktisk går den gjennom, hvorfor?

(For bakgrunn, er den ovennevnte typen ment å være en "enten denne egenskapen eller den egenskapen, men ikke begge, type". Se Typescript-grensesnitt - Er det mulig å gjøre "en eller den andre" egenskaper påkrevd?)

Svar #1

Ifølge blogginnlegget som introduserer kontroll av overflødig unionsegenskap i TypeScript 3.5, vil TypeScript sjekke at det tilhører minst én type:

I TypeScript 3.4 og tidligere var visse overflødige egenskaper tillatt i situasjoner hvor de egentlig ikke burde ha vært det. For eksempel tillot TypeScript 3.4 den feilaktige name-egenskapen i objektbokstaven selv om typene ikke stemmer mellom Point og Label.

type Point = {
    x: number;
    y: number;
};

type Label = {
    name: string;
};

const thing: Point | Label = {
    x: 0,
    y: 0,
    name: true // uh-oh!
};

Tidligere ville en ikke-diskriminert union ikke få gjort noen sjekk av overflødig egenskap på medlemmene sine, og som et resultat glapp den feilaktig typede navneegenskapen forbi.

I TypeScript 3.5 sjekker typetesten i det minste at alle de oppgitte egenskapene tilhører et union-medlem og har riktig type, noe som betyr at eksemplet ovenfor korrekt utløser en feil.

Blogginnlegget fortsetter med å eksplisitt beskrive overlapp som gyldig:

Merk at delvis overlapp fortsatt er tillatt så lenge eiendomstypene er gyldige.

const pl: Point | Label = {
    x: 0,
    y: 0,
    name: "origin" // okay
};

Basert på uttrykket «alle de oppgitte egenskapene tilhører medlem av en union og har riktig type», ser det ut til at kontrollen for overflødige egenskaper ikke klarer å behandle disse egenskapene som gjensidig utelukkende.

Relaterte artikler