Reputation: 11920
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:
isSuccess
and isError
must be oppositesdata
will have value T
if isSuccess
is true, and be undefined
if isSuccess
is falseIs this kind of thing possible with typescript?
Upvotes: 1
Views: 121
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