Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Type Alias as Discriminating Union

I’ve written a fairly complex definition file to match the behavior of an existing JavaScript library

export declare interface XcodeBaseFileTreeObject {
    path: string;
    includeInIndex?: 0 | 1;
    usesTabs?: 0 | 1;
    indentWidth?: number;
    tabWidth?: number;
    wrapsLines?: 0 | 1;
}

export declare interface XcodeUngroupedFileTreeObject extends XcodeBaseFileTreeObject {
    sourceTree: `"<absolute>"` | "SOURCE_ROOT" | "DEVELOPER_DIR" | "BUILT_PRODUCTS_DIR" | "SDKROOT";
    name: string;
}

export declare interface XcodeGroupedFileTreeObject extends XcodeBaseFileTreeObject {
    sourceTree: `"<group>"`;
}

export declare type XcodeAbstractFileTreeObject = XcodeGroupedFileTreeObject | XcodeUngroupedFileTreeObject;

export declare type PBXBaseFileReference = XcodeAbstractFileTreeObject & {
    readonly isa: "PBXFileReference";
    fileEncoding?: 4 | 10;
    lineEnding?: 0 | 1 | 2;
    languageSpecificationIdentifier?: string;
    xcLanguageSpecificationIdentifier?: string;
    plistStructureDefinitionIdentifier?: string;
};

export declare type XcodeFileType = "archive.ar" | "archive.asdictionary" | "archive.binhex";

export declare type PBXInferredFileReference = PBXBaseFileReference & {
    lastKnownFileType: XcodeFileType;
};

export declare type PBXExplicitFileReference = PBXBaseFileReference & {
    explicitFileType: XcodeFileType;
};

export declare type PBXFileReference = PBXInferredFileReference | PBXExplicitFileReference;

Some union types as properties have been shortened for brevity, but the gist here is that I have a discriminating union from which another type is meant to inherit from, and in turn, another discriminating union is meant to inherit from that type. When I use the union at the bottom of the tree in a function like this:

function getFileType(file: PBXFileReference): XcodeFileType {
    return file.lastKnownFileType ?? file.explicitFileType;
}

I get an error that neither lastKnownFileType nor explicitFileType exist on PBXFileReference. In fact, neither property even comes up in the autocomplete when I’m writing that. I was expecting that to act as a typical discriminating union, where if one of those values isn’t defined, it falls back on the other one definitely existing. How can I achieve the structure I’m looking for?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You can use a ternary expression and use in to check for the property before accessing it:

function getFileType(file: PBXFileReference): XcodeFileType {
  return 'lastKnownFileType' in file ? file.lastKnownFileType : file.explicitFileType;
}

TypeScript playground

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading