Javascript Conditional Inside TypeScript Interface

No there's not. The best thing to do is to create separate interfaces that describe the two different types of data.

For example:

interface SublistItem {
    sublistId: 'item';
    fieldId: 'itemname' | 'quantity';
}

interface SublistPartners {
    sublistId: 'partners';
    fieldId: 'partnername' | 'location';
}

function getData(): SublistItem | SublistPartners {
    return (Math.random() < 0.5)
        ? { sublistId: 'item', fieldId: 'itemname' }
        : { sublistId: 'partners', fieldId: 'partnername' };
}

const someValue = getData();

if (someValue.sublistId === "item") {
    // SublistItem in here
}
else {
    // SublistPartners in here
}

If you would like to completely separate out your interfaces you could do something like this:

eg. sublist.model.ts

interface SublistItem {
    sublistId: 'item';
    fieldId: 'itemname' | 'quantity';
}

interface SublistPartners {
    sublistId: 'partners';
    fieldId: 'partnername' | 'location';
}

export type Sublist = SublistItem | SublistPartners;

Now you can use the Sublist type and it will correctly infer whether it is of type SublistPartners or SublistItem depending on the field values you provide.


You can try to solve this problem using conditional types:

interface SublistItem {
    sublistId: 'item';
    fieldId: 'itemname' | 'quantity';
}

interface SublistPartners {
    sublistId: 'partners';
    fieldId: 'partnername' | 'location';
}

type ConditionalSublist<bIsSublistItem=true> = bIsSublistItem extends true ? SublistItem : SublistPartners;

let sublistItem: ConditionalSublist<true> = {
    fieldId: "itemname",
    sublistId: "item"
};

let sublistPartner: ConditionalSublist<false> = {
    fieldId: "partnername",
    sublistId: "partners"
};