Home > Enterprise >  Typescript seemingly not resolving undefined correctly
Typescript seemingly not resolving undefined correctly

Time:10-01

In the following code I expect the API payload to contain either a shareholderCompany or a shareholderExternalPerson and whichever one resolves as being true will trigger a function call as seen below. For some reason it seems to think in the child function that the shareholderCompany is undefined.

export const upsert = async(serviceData: any, companyShareholder: CompanyShareholdersDefinitionInterface, { transaction }: any) => {
    const { shareholderCompany, shareholderExternalPerson } = companyShareholder;

    if (shareholderCompany) {
        return upsertCompanyShareholderCompany(serviceData, companyShareholder, { transaction });
    }
    if (shareholderExternalPerson) {
        return upsertCompanyShareholderPerson(serviceData, companyShareholder, { transaction });
    }
}

export const upsertCompanyShareholderCompany = async(serviceData: any, companyShareholder: CompanyShareholdersDefinitionInterface, { transaction }: any) => {
    const { company_id, source, class: shareholderClass, shareholderCompany } = companyShareholder;
    // Says that shareholderCompany might be undefined

These are the types:

export type CompanyShareholdersDefinitionInterface = CompanyShareholdersCompanyInterface | CompanyShareholdersExternalPersonInterface;

interface CompanyShareholdersCompanyInterface {
    shareholderCompany: CompanyDefinitionInterface,
    shareholderExternalPerson?: ExternalPersonDefinitionInterface
}

interface CompanyShareholdersExternalPersonInterface {
    shareholderCompany?: CompanyDefinitionInterface,
    shareholderExternalPerson: ExternalPersonDefinitionInterface
}

What am I missing here that's causing it to complain?

CodePudding user response:

With your upsertCompanyShareholderCompany definition, you are telling TypeScript that companyShareholder is CompanyShareholdersDefinitionInterface, which is either CompanyShareholdersCompanyInterface or CompanyShareholdersExternalPersonInterface, the latter of which has an optional shareholderCompany, so it can be undefined.

I think companyShareholder should be type CompanyShareholdersCompanyInterface instead:

export const upsertCompanyShareholderCompany = async(serviceData: any, companyShareholder: CompanyShareholdersCompanyInterface, { transaction }: any) => {
    const { shareholderCompany } = companyShareholder;
    // Always CompanyDefinitionInterface
}

Which moves the problem up to your upsert function because you can't invoke upsertCompanyShareholderCompany with a companyShareholder of type CompanyShareholdersDefinitionInterface. You can introduce a typeguard that will narrow it:

function isCompanyShareholdersCompany(inp: CompanyShareholdersDefinitionInterface): inp is CompanyShareholdersCompanyInterface{
    return !!inp.shareholderCompany;
}

Which would make your upsert function look something like this:

export const upsert = async(serviceData: any, companyShareholder: CompanyShareholdersDefinitionInterface, { transaction }: any) => {
    if (isCompanyShareholdersCompany(companyShareholder)) {
        // companyShareholder is of CompanyShareholdersCompanyInterface type
        return upsertCompanyShareholderCompany(serviceData, companyShareholder, { transaction });
    }
    
    // companyShareholder can only be CompanyShareholdersExternalPersonInterface now
    return upsertCompanyShareholderPerson(serviceData, companyShareholder, { transaction });
}
  • Related