I have a typeScript interface like below –
interface MovieStar {
birth: ActorAddress;
actorWiki: ActorDescription | ActorByMovie;
}
interface ActorAddress {
city: string;
state: string;
country: string
}
interface ActorDescription {
name: string;
hobby: string;
}
interface ActorByMovie extends ActorDescription {
movieName: string;
}
When I am trying to use the interface movieStar
and access actorWiki
, I am getting only common properties of ActorDescription
and ActorByMovie
and I am not able to access movieName.
My requirement: I am using React with TypeScript and I have assigned movieStar
as a type for the data fetched from an API.
Now, I have another API the response of which is similar in structure, but has one extra property called movieName
which I am not able to access.
Am I doing something wrong here or shall I structure my interface in some other way? I came across the concept of Discriminated Unions but I think it is useful when we want both scenarios in one component (discriminated based on type). Here, I want the interface with extra properties in a separate component itself.
2
Answers
Based on your description, it seems like you’re encountering an issue due to the union type
actorDescription | actorByMovie
within yourMovieStar
interface. TypeScript will only allow you to access properties that are common to all types in the union when you try to accessactorWiki
. This is why you’re unable to accessmovieName
directly, as it’s not a property onActorDescription
.Even though you mentioned that you might not need Discriminated Unions since you’re handling different scenarios in separate components, they could still offer a solution to your problem. The key here is to provide a way for TypeScript to differentiate between the two types at runtime, which can then be used to safely access properties specific to one type.
To achieve this, you can introduce a discriminant property (commonly a type property) to your interfaces. Here’s how you can adjust your interfaces to use Discriminated Unions effectively:
With this setup, you can use a type guard to check the type property and TypeScript will then allow you to access properties specific to that type:
This way, you can use the same
MovieStar
interface but still differentiate between the cases when you have additional properties to access. This approach keeps your types flexible and allows you to use them in different components as needed, while still maintaining type safety.Depending on your use case you might be able to simply narrow
MovieStar["wiwactorWiki"]
with thein
-operator.TypeScript Playground
Another approach I find reasonable based on your problem description is to declare
movieName
as optional insideActorDescription
. That way you can save yourself an interface.movieName
will bestring | undefined
but you can narrow it tostring
as explained above.TypeScript Playground