typescript - Varför är dessa strukturellt liknande typer inkompatibla?
Om jag deklarerar följande typer:
export type Type1 = { id: string } | { id: number };
export type Type2 = { id: string } | { id: number };
Varför får jag ett fel när det används på följande sätt:
function displayItem(item: Type1) {
loadItem({ id: item.id }); // error is indicated here
}
function loadItem(item: Type2) {}
Min förståelse från https://www.typescriptlang.org/docs/handbook/type-compatibility.html är att de bör vara likvärdiga eftersom de är strukturellt desamma.
Enklare återgivning med tanke på svaren (andra typen behövs inte):
export type Type1 = { id: string } | { id: number };
function displayItem(item: Type1) {
loadItem({ id: item.id }); // error is indicated here
}
function loadItem(item: Type1) {}
Svar #1
På djupet försöker du tilldela ett värde av typen number | string till antingen number eller en string.
Eftersom du får åtkomst till item.id, kan id vara string eller number, enligt din typdefinition. Din Type2 förväntar sig ett objekt {id: string} eller {id: number} vilket är annorlunda än {id: string | number}.
Så, två olika scenarier skulle kunna lösa denna missöde.
- Deklarera din
Type2för att förvänta en nyckel som heteridsom ärnumber | string - Skicka hela
item-objektet till din andra funktion. Detta är det så kallade typkompatibilitet.
Svar #2
Det är inte så att Type1 inte är ekvivalent med Type2
Till exempel kommer följande inte att ge ett fel
function displayItem(item: Type1) {
loadItem(item);
}
function loadItem(item: Type2) {}
Problemet uppstår när du skriver item.id vilket kan vara två saker. Eftersom Type1 är definierad som export type Type1={ id: string } | { id: number }; kan typen på denna variabel vara string eller number. Så TypeScript skapar en annan typ för {id: item.id} som är {id: number | string}, och som du kan se är den inte kompatibel med Type2.
Du måste uttryckligen skriva vilken typ du vill använda.
Följande kommer inte att ge något fel
function displayItem(item: Type1) {
loadItem({ id: item.id as number});
}
Nu markerar jag item.id som number så typen av { id: item.id as number} är {id: number} vilket är kompatibelt med Type2
Ändra bara dina typer till följande
export type Type1 = { id: string | number};
export type Type2 = { id: string | number};
