dwjohnston
dwjohnston

Reputation: 11920

Define typescript interface with conditional values

Let's say I want to create an interface that looks like this:

interface DataStatus<T> {
   isSuccess: boolean; 
   isError: boolean;
   data: T | undefined; 
}

And later on I'm going to be using this like:

interface Foo {
   id: string; 
   name: string; 
}

function fetchData() : DataStatus<Foo> {
   //implementation
}


const ds = fetchData(); 

if (ds.isSuccess) {
   console.log(ds.data.name); //TS Warning - ds.data might be undefined
}

What I'd like to do add some conditions to the DataStatus interface with these rules:

Is this kind of thing possible with typescript?

Upvotes: 1

Views: 121

Answers (1)

Shanon Jackson
Shanon Jackson

Reputation: 6581

Yes, you can if you have a discriminated union.

interface ISuccessDataStatus<T> {
   isSuccess: true; 
   isError: false;
   data: T; 
}

interface IFailureDataStatus<T> {
   isSuccess: false; 
   isError: true;
   data: undefined; 
}


type PossibleStatus<T> = ISuccessDataStatus<T> | IFailureDataStatus<T>;


declare const hello: PossibleStatus<{ name: "john" }>

if (hello.isSuccess) {
    const whatType = hello.data; // T and not T | undefined
}

const whatType = hello; // PossibleDataStatus; (outside the if block)

Typescript is smart enough to figure out when hello.isSuccess is true inside that block where it knows it's true it will narrow down the type of hello to ISucessDataStatus instead of the union.

Upvotes: 3

Related Questions