Reputation: 1334
I defined these types:
type ItemWithName = {
type: "ItemWithName";
name: string;
a: { name: string } ;
};
type ItemWithValue = {
type: string;
name: string;
b: { value: number } ;
};
export type Item = ItemWithName | ItemWithValue;
And I have a function to extract a certain value from an object:
const extractValue = (item: Item) => {
switch (item.type) {
case "ItemWithName":
return item.a.name; // TS2339: Property 'a' does not exist on type 'Item'.
case "ItemWithValue":
return item.b.value;
}
};
But I get this error: TS2339: Property 'a' does not exist on type 'Item'.
I'm not entirely sure how to make TypeScript understand that if the type of the object is "ItemWithValue", there's a property a.
Note: this is a small abstraction of my particular issue, in reality I have several more of these types.
The expected behaviour is that TypeScript detects that the item is of type ItemWithName
if the object has a type value of "ItemWithName"
Upvotes: 0
Views: 842
Reputation: 116
Unfortunately this doesn't currently work with Typescript.
Here's an issue on GitHub about a similar problem.
type-fest has a wrapper type LiteralUnion
for the problem referenced in the issue. However you can't just use it like
type Item = LiteralUnion<ItemWithName, ItemWithValue>
.
So these are my two possibilities at the moment:
const extractValue = (item: Item) => {
switch (item.type) {
case "ItemWithName":
const itemWithName = item as ItemWithName;
return itemWithName.a.name;
case "ItemWithValue":
return item.b.value;
}
};
Note: this is a small abstraction of my particular issue, in reality I have several more of these types.
Instead of using
type ItemWithValue = {
type: string;
name: string;
b: { value: number } ;
};
you could create a type which unions all possible types like
type ItemWithValue = {
type: 'ItemWithValue' | 'OtherItemWithValue' | 'AgainAnItemWithValue';
name: string;
b: { value: number } ;
};
It would be really cool to use type: Exclude<string, 'ItemWithName'>
. But this also would not work as you can see in this discussed question.
Upvotes: 2