LWC NavigationMixin is not recognised by code inspections
If you write an LWC using NavigationMixin (https://developer.salesforce.com/docs/component-library/bundle/lightning-navigation/documentation), both the import and the usage are flagged as being unrecognised by IC2.
For example (from the above page):
import { NavigationMixin } from 'lightning/navigation';
export default class Example extends NavigationMixin(LightningElement) {
navigateToObjectHome() {
// Navigate to the Account home page
this[NavigationMixin.Navigate]({
type: 'standard__objectPage',
attributes: {
objectApiName: 'Account',
actionName: 'home',
},
});
}
Line 1 has a warning that NavigationMixin
is an unresolved symbol. And then this[NavigationMixin.Navigate]
is also unrecognised.
Comments (17)
-
repo owner -
repo owner Aidan, I just committed a fix for this, but I'm not entirely happy with it. Basically I added the following mixin definition to the corresponding
.d.ts
file:class NavigationMixinType { GenerateUrl(pageReference: object): Promise<string>; Navigate(pageReference: object, replace?: boolean): void; } export function NavigationMixin<SuperclassType extends typeof LightningElement>(superclass: SuperclassType): SuperclassType & NavigationMixinType;
With that in place, the following all properly evaluates without inspection errors:
import {LightningElement} from 'lwc'; import {NavigationMixin} from "lightning/navigation"; export default class Example extends NavigationMixin(LightningElement) { recordPageUrl; doSomething() { this[NavigationMixin.Navigate]({ type: 'standard__objectPage', attributes: { objectApiName: 'Account', actionName: 'home' } }); this[NavigationMixin.GenerateUrl]({ type: 'standard__recordPage', attributes: { recordId: 'xxxyyyzzz', actionName: 'view' } }).then(url => { this.recordPageUrl = url; }); } }
However, the IDE doesn't provide
Navigate
orGenerateUrl
code completions from theNavigationMixin.
stem in thethis[NavigationMixin.*]
expressions.I confess that I'm far from a TypeScript/ES6 expert (and that's actually gross understatement), so perhaps this isn't the right way to define an ES6 mixin in a TypeScript definition file? I also saw several threads on the topic that said this this stuff is still not 100% baked.
If you're aware of a better way to define this that addresses the code inspection issues while also providing the correct code completions, please feel free to let me know.
-
reporter Thanks, Scott!
I’m afraid I can’t suggest any better solutions. I’m a novice with TS, and perhaps a beginner with LWCs. I’ve sent this thread to someone who is more knowledgeable than me, so hopefully, they will be able to comment on any possibility of a neater solution.
-
I haven’t really done any lwc dev so I’m not familiar with the
NavigationMixin
… I also haven’t really used the “mixin” pattern much but there’s decent documentation…Declaring ambient types is often more confusing and harder than typing the implementation. This github issues explains how to do it for mixins.
We also need to leverage declaration merging to provide the static
GenerateUrl
properties (not sure why these are really needed… why not just call the method by name directly?).Putting all of that together, I think you’d actually want something like this:
declare class NavigationMixin { static readonly GenerateUrl = 'GenerateUrl'; static readonly Navigate = 'Navigate'; } type Constructor<T = {}> = new (...args: any[]) => T; declare class NavigationElement { public GenerateUrl(pageReference: object): Promise<string>; public Navigate(pageReference: object, replace?: boolean): void; } declare function NavigationMixin<T extends Constructor<LightningElement>>( superClass: T, ): Constructor<NavigationElement> & T;
-
repo owner Thanks, Charlie! That actually works perfectly. And it kind of taught me something about TypeScript, though without actually using it on a regular basis, it's still pretty muddy to me. Nonetheless, I appreciate the guidance!
-
np! I enjoy writing typings waaaay more than I should
PS: I’d also type
pageReference
if possible. Should really improve the dev experience. In typescript,object
should be avoid as much asany
-
repo owner Yeah, I looked into that. One of the issues with
PageReference
is that its attributes vary based on the referenced page type:I assume I'd just need to kitchen sink that type with the union of all possible attributes?
-
@Scott Wells actually at first glance it should be possible to provide true type-safety here. This is where typescripts algebraic typing and type-inference really is a thing of beauty!
This should give you an idea of how it might work. I think the challenge here would be translating there docs into accurate domain model types as it’s maybe not totally clear what is allowed.
-
repo owner Once again, thanks, @Charlie Jonas. I'd actually started doing something similar, but as before it was missing some key aspects. I'm still seeing two issues, though, both of which may be limitations in the current JetBrains TS support:
- When I use your TS Playground example, it's not unambiguously resolving, say,
type
to the correctPageReference
variant based on its value: - When I use the
this[NavigationMixin.Navigate](...)
syntax with the params of that function strongly-typed toPageReference
, it doesn't seem to see that as an invocation ofNavigate
.
So as I said, these might just be (known?) limitations of the JetBrains TS functionality. I'll try stitching it all together in TS Playground to see if it works as expected/desired there, and if it does but doesn't in the JetBrains IDEs, I'll log a support ticket with them accordingly.
Thanks (yet) again!
- When I use your TS Playground example, it's not unambiguously resolving, say,
-
It should work: Playground Link.
It’s likely that this requires one of the more recent version of typescript. Maybe check what version your JetBrains project is using.
-
The other culprit would be your ts-config.json. Some of the more complex type inference features can only work if you are using the
strict
settings. -
repo owner I just copy/pasted that TS Playground snippet into a JetBrains TypeScript scratch window and, while everything validates properly, it's definitely not able to infer unambiguous references to the various
PageReference
types:The bundled version of TypeScript is 4.2.2. It looks like the latest is 4.2.4? Would you expect this type of behavioral difference in two patch-level releases? Also, that occurs with
"use strict";
at the top of the file which should(?) force strict behavior, correct?Sorry for what may be dumb questions. This is now so far out of my area of expertise as to be silly, but I'm enjoying the education!
-
Ya being off by 2 patch versions shouldn’t make any difference.
"use strict";
actually is a javascript thing and doesn’t have any impact on the typescript LSP (AFIK).What I was referring to is the tsconfig strict property.
However, enabling this in a project that wasn’t previously using it is likely to create a bunch of errors! I’m not sure which config property(s) is actually the culprit here.
In general, if your tsconfig & typescript version matches that of the ts-playground, you should see the same behavior.
-
repo owner In general, if your tsconfig & typescript version matches that of the ts-playground, you should see the same behavior.
Maybe, maybe not. I know that the JetBrains TS stuff can be configured to the use the TypeScript language server, but I also know that they're doing quite a bit of parsing, type inference, and reference evaluation themselves just as they do with all of their other language plugins (and just like IC does for the Salesforce-specific languages). I just disabled use of the language server and I still see the same behavior, so I'm fairly certain it's their own parser doing this.
I'll log a bug with them. I'll go ahead and add
PageReference
as you've started to define it as it does provide much improved code completion and validation vs. justobject
, but it looks like it's not quite perfect.Thanks again!
-
repo owner Actually I take back the last thing I said above. Code completion and validation work well when the client code is in TS, but when it's in JS/ES6, not so much. The good news is that the original mix-in declarations work pretty well, so I'll include them in the next build of IC2; the bad news is that the attempt at providing a strongly-typed
PageReference
doesn't work any better than just usingobject
. It certainly should...but it doesn't. I'll see if I can distill it into a very simple reproducible test case and log a bug with JetBrains. Thanks! -
repo owner - changed status to resolved
Delivered in 2.1.7.4. If/when JB provides a fix for the issues with
PageReference
I'll add that as well, but for now at the very least,NavigationMixin
should work properly. -
repo owner - removed version
Removing version: Unassigned (automated comment)
- Log in to comment
Got it. I'll address it for next week's build. Thanks!