@Input 属性的角度指令类型检查

问题描述 投票:0回答:0

我创建了一个 lazyLoad 指令来处理延迟加载组件。

@Directive({
    selector: '[lazyComponent]',
})
export class LazyCompDirective<I, T extends LazyLoadedComponent<I>> implements OnInit, OnDestroy {
    private _inputs: I|null = null;
    private compRef: ComponentRef<T>|null = null;
    private readonly subscription = new Subscription();
    private type?: Type<T>;

    @Input('frLazyComponent') public set component(type: Type<T>) {
        if (type) {
            this.compRef = this.viewContainerRef.createComponent(type);
            this.refreshInputs(this._inputs);
            this.type = type;
        }
    }

    @Input() public set inputs(data: I) {
        if (this.compRef) {
            this.refreshInputs(data);
            (this.compRef).hostView.detectChanges();
        } else {
            this._inputs = data;
        }
    }

    public constructor(private readonly viewContainerRef: ViewContainerRef) {}

    ngOnInit(): void {
        if (this.type) {
            this.compRef = this.viewContainerRef.createComponent(this.type);
            this.refreshInputs(this._inputs);
        }
    }

    public ngOnDestroy() {
        this.compRef = null;
        this.subscription.unsubscribe();
    }

    private refreshInputs(inputs: I | null) {
        if (inputs) {
            Object.keys((inputs)).forEach(inputName => {
                // @ts-expect-error: skip error
                (this.compRef as ComponentRef<unknown>).instance[inputName] = inputs[inputName];
            });
        }
    }

    static ngTemplateContextGuard<T extends LazyLoadedComponent<I>, I>(_dir: LazyCompDirective<I, T>, _context: unknown): _context is LazyLoadedComponent<I> {
        return true
    }

    static ngTemplateGuard_inputs<T extends LazyLoadedComponent<I>, I>(_dir: LazyCompDirective<I, T>, _state: I): _state is I {
        return true;
    }
}

所以我们可以将此属性用作

<ng-template [lazyComponent]="component" [inputs]="componentInput"></ng-template>

我们定义了这个接口,所以我们总是可以有一个带有指令的强类型

export interface LazyLoadedComponent<I> {
    inputs?: I;
}

加载我们需要实现这个接口的组件

@Component({
    selector: 'lazy-component',
    template: '<div>I'm Lazy</div>',
})
export class LazyComponent implements LazyLoadedComponent<LazyComponentInput>, OnInit {
    public inputs?: LazyComponentInput;

    public constructor(
        
    ) {}

    public ngOnInit(): void {}
}

惰性组件输入

export interface LazyComponentInput{
a: string,
b: number,
}

我发现

[inputs]
并没有真正检查类型是否有效。

我觉得我的类型检查守卫是错误的,但我不知道我应该如何检查类型。有谁知道我应该如何修复类型检查?

angular angular-directive angular-lazyloading
© www.soinside.com 2019 - 2024. All rights reserved.