Support apex constants in LWC

Issue #2557 resolved
Oleksandr Tymchenko created an issue

Hello,
This type of constants works great in apex, but when using them in lwc, suggestions doesn’t work.
https://github.com/beyond-the-cloud-dev/apex-consts

Example code

public class ContactConsts {
    public static final ContactConsts INSTANCE = new ContactConsts();

    @AuraEnabled
    public final Status STATUS = new Status();

    public class Status {
        @AuraEnabled
        public final String IN_APPROVAL_PROCESS = 'In Approval Process';
        @AuraEnabled
        public final String ACTIVATED = 'Activated';
        @AuraEnabled
        public final String DRAFT = 'Draft';
    }
}



public class Consts {
   @AuraEnabled
    public static final ContactConsts CONTACT {
        get {
            return ContactConsts.INSTANCE;
        }
    }

     @AuraEnabled
    public static Consts getConstants() {
        return new Consts();
    }
}

Is any change that calling import getConstants from '@salesforce/apex/Consts.getConstants'; will assist as the same way in LWC/Aura as it’s assisting in Apex?

BTW. Line 21 (public static final ContactConsts CONTACT) highlighted with text “@AuraEnabled properties cannot be static”, however deployment works.

Many thanks!

Comments (11)

  1. Scott Wells repo owner

    After playing with this a bit, I have a few questions about what’s being asked and a few thoughts on the behavior here.

    First, I’m quite surprised that @AuraEnabled properties can be static but @AuraEnabled fields cannot be static. In other words, deploying the following:

    public with sharing class Issue2557Constants {
        @AuraEnabled public static final Issue2557 AURA_ENABLED_PROPERTY { get { return Issue2557.INSTANCE; } }
        @AuraEnabled public static final Issue2557 AURA_ENABLED_FIELD = Issue2557.INSTANCE;
    }
    

    fails with:

    ERROR at line 3, column 48 - AuraEnabled fields cannot be static
    

    I just have to assume that because properties have method-like getters and setters, they’re treated as methods here instead of as fields. I’ve updated IC2’s Modifier Agreement Inspection to allow for @AuraEnabled static properties.

    Now regarding your question:

    Is any change that calling import getConstants from '@salesforce/apex/Consts.getConstants'; will assist as the same way in LWC/Aura as it’s assisting in Apex?

    I’m seeing completions working quite well in LWC, both for creation of the import statement using the importapex live template and for completion when used via a Promise:

    and when used via async/await:

    Can you please elaborate on the remaining part of your question so I understand whether there’s anything else to do aside from addressing the false static code analysis positive for the property?

  2. Oleksandr Tymchenko reporter

    Hi,
    Thank you for your quick response.
    when you assigning it to a local variable - suggestions works :)
    I think I found reasons why it doesn`t work.
    1)
    I had created lwc variable, later
    this.constants = await getConstants() → doesn’t suggest
    2) When using js utils method

    create lwc utils with only js
    import getApexConstants from "@salesforce/apex/Constants.getConstants";

    const getConstants = () => {
        return new Promise((resolve, reject) => {
            getApexConstants()
                .then((result) => {
                    resolve(result);
                })
                .catch((error) => {
                    reject(error);
                });
        });
    };
    
    export { getConstants };
    

    In target lwc
    import { getConstants } from "c/Utils";

    const constants = await getConstants() ->doesn’t work.

  3. Scott Wells repo owner

    Okay, I was able to reproduce that. That seems to be another issue with the JetBrains JavaScript/TypeScript plugin’s type inference capabilities with that level of indirection away from a dynamically-attributed data type, specifically the translation of the Apex method’s return type into JS/TS. There are quite a few improvements coming in the next few JetBrains releases including some of the near-term patch-level releases as described here (toward the end of the issue thread):

    https://youtrack.jetbrains.com/issue/WEB-65796

    Unfortunately there’s not much I can do as I’m already adding as much type information as possible, but if this isn’t resolved in the next several JetBrains updates, I’ll follow up with them to let them about this specific use case.

  4. Scott Wells repo owner

    Resolving as the remaining issue is due to some previously-reported issues in the JetBrains plugin's type inference/propagation mechanisms.

  5. Scott Wells repo owner

    Note that as a workaround, you can add an explicit type hint comment to the exported method, e.g.:

    /** @return {Promise<{AURA_ENABLED_PROPERTY: {STATUS: {IN_APPROVAL_PROCESS: string, ACTIVATED: string, DRAFT: string}}}>} */
    const getConstants = () => {
      ...
    };
    

  6. Scott Wells repo owner

    Actually I’m wrong. The issue here is that new Promise(...) loses the data type since Promise is a parameterized type. Because the parameter data type is a dynamic translation of an Apex method return type, though, there’s no good way to add the type params. However, the following version of that util class should be the same assuming you don’t need to modify the result/error of the imported Apex method proxy:

    import getApexConstants from "@salesforce/apex/Constants.getConstants";
    
    const getConstants = () => {
        return getApexConstants();
    };
    
    export { getConstants };
    

    And that properly retains the strongly-type result for downstream importers.

  7. Log in to comment