Reputation: 11803
What I want to do is pretty simple:
I have an type Foo
, but there's cases where the Foo might be empty, so we have a union type with an empty object. (The use case here is actually with Redux, which doesn't let you have a redux state initalised as undefined).
interface Foo {
id: string;
data: string;
}
type PotentialFoo = Foo | {};
Later, when I'm using one of these PotentialFoo
s, an easy way to check if it's a Foo or not, is to check if one of the fields exist.
But the TypeScript compiler doesn't like this.
const itemA: PotentialFoo = {
id: "foo",
data :"data",
}
const itemB: PotentialFoo = {};
function someFunct(item: PotentialFoo) {
if (item.id) { // Property 'id' does not exist on type '{}'.
//handle it as a Foo.
}
}
Is there a way to to otherwise allow a discrimination here, like TypeScript allows in other cases?
Upvotes: 3
Views: 1543
Reputation: 249606
The simplest solution in this case is to use an in
check as a type guard:
function someFunct(item: PotentialFoo) {
if ('id' in item) {
item.data // ok
}
}
Upvotes: 8
Reputation: 11803
One solution is to use a TypeScript type predicate, which is essentially to create a boolean function to determine the type, like you have here, but gives better compiler hints to TypeScript.
const itemA: PotentialFoo = {
id: "foo",
data :"data",
}
const itemB: PotentialFoo = {};
function isFoo(item: PotentialFoo) : item is Foo {
return !!(item as Foo).id;
}
function someFunct(item: PotentialFoo) {
if (isFoo(item)) {
//handle it as a Foo.
}
}
Upvotes: 2