Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Structural directives documentation does not mention type guards #33905

Closed
Airblader opened this issue Nov 18, 2019 · 6 comments
Closed

Structural directives documentation does not mention type guards #33905

Airblader opened this issue Nov 18, 2019 · 6 comments
Assignees
Labels
feature Issue that requests a new feature freq2: medium state: has PR
Milestone

Comments

@Airblader
Copy link
Contributor

Description

The documentation for structural directives make no mention of type guards for either inputs or the context (ngTemplateGuard_x, ngTemplateContextGuard). However, especially with Ivy this will be important information for anyone looking to write custom structural directives.

What's the affected URL?**

https://angular.io/guide/structural-directives

@Airblader
Copy link
Contributor Author

The corresponding implementations in NgIf¹ and NgForOf² do comment on this fairly well, which I assume is due to this being emitted into thee API docs. But I think it would be good to actually put it into the above mentioned guide.

¹ https://github.com/angular/angular/blob/8.2.14/packages/common/src/directives/ng_if.ts#L227
² https://github.com/angular/angular/blob/8.2.14/packages/common/src/directives/ng_for_of.ts#L267

@kapunahelewong kapunahelewong added comp: docs freq2: medium feature Issue that requests a new feature labels Nov 18, 2019
@ngbot ngbot bot modified the milestone: Backlog Nov 18, 2019
@jbogarthyde
Copy link
Contributor

jbogarthyde commented Nov 20, 2019

@Airblader Can you suggest what needs to be said about it? I assume it would be in the last section, the example of defining a custom structural directive.
Should that example be updated to show how to enable type-checking in your directives? Or does it need a different example?
Should anything be added to https://next.angular.io/guide/template-typecheck? The custom structural directive doc could reference that page, and vice versa.

@Airblader
Copy link
Contributor Author

Can you suggest what needs to be said about it?

I was thinking along the lines of

Narrowing types for inputs

If an input of your structural directive can actually narrow the type of the given expression inside the template, you can let Angular know about this by adding a static ngTemplateGuard_xyz property where xyz is the name of the input. This property can either be the type-narrowing function based on its return type, or the special string "binding" if the expression itself should be used to narrow the type.

Examples:

@Directive({…})
export class ExampleDirective {
    @Input() set inputA(val: string | null) { 
        this._val = val === null ? '' : val;
    }

    @Input() inputB: boolean;

    // Although inputA can also be null, we know that we will never render the
    // template if it is, therefore we can tell the compiler that inside the template
    // null is not an option.
    static ngTemplateGuard_inputA: (dir: ExampleDirective, expr: string | null): expr is string => true;

    // Use the bound expression itself, i.e. [inputB]="person !== null" would now properly
    // infer that inside the template, "person" can no longer be null.
    static ngTemplateGuard_inputB: 'binding';

    // …
}

An example for the latter is *ngIf which uses the passed expression to narrow the type as the template will only be instantiated if the expression is truthy.

Typing the directive's context

If your structural directive provides a context to the instantiated template, you can properly type it inside the template by providing a static ngTemplateContextGuard function. This informs the Ivy's template checker of the proper type and improves type-checking for the template.

Example:

@Directive({…})
export class ExampleDirective {
    // Make sure Ivy's template checker knows the type of the context with which the
    // template of this directive will be rendered
    static ngTemplateContextGuard(dir: ExampleDirective, ctx: unknown): ctx is ExampleContext => true;

    // …
}

Please note that it might be worth having someone double-check the accuracy of these descriptions (who knows, maybe I'm misunderstanding them).


Should anything be added to https://next.angular.io/guide/template-typecheck? The custom structural directive doc could reference that page, and vice versa.

Yeah, sounds like a great idea. :-)

@Airblader
Copy link
Contributor Author

BTW, there's a very similar ngAcceptInputType_* feature which is documented already, so it can serve as a good reference: https://next.angular.io/guide/aot-compiler#input-setter-coercion

@Airblader
Copy link
Contributor Author

@mhevery @jbogarthyde This issue can be closed, right? The PR has been merged and is live on the website.

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Aug 27, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature Issue that requests a new feature freq2: medium state: has PR
Projects
None yet
Development

No branches or pull requests

3 participants