简体   繁体   English

如何在@input() 变量上使用类型断言?

[英]How to use type assertion on @input() variable?

I have created a union type of several interfaces that share a common parent through inheritance.我创建了多个接口的联合类型,这些接口通过 inheritance 共享一个共同的父级。 That union type is passed on to specific components.该联合类型被传递给特定组件。 Those components will only ever be one of the child types.这些组件永远只是子类型之一。 How can I assert the type on the child component?如何在子组件上声明类型?

Example:例子:

interface Common {
  a: string;
  b: string;
}

interface Child1 extends Common {
  c: string;
}

interface Child2 extends Common {
  d: string;
}

type Union = Child1 | Child2;

The parent component has a variable父组件有一个变量

data: Union;

and passes it to child components like so:并将其传递给子组件,如下所示:

<app-child1 [data]="data"></app-child1>
<app-child2 [data]="data"></app-child2>

The child component will only ever be one of those types so I should be able to assert it somehow:子组件只会是其中一种类型,所以我应该能够以某种方式断言它:

@Input() data: Child1;

Currently this will throw a type error claiming Child1 is missing properties.目前这将引发类型错误,声称 Child1 缺少属性。

I've tried these @Input() data: Union as Child1;我试过这些@Input() data: Union as Child1; and <app-child1 [data]="data as Child1"> but those just break.<app-child1 [data]="data as Child1">但那些只是打破。

How can I assert this correctly?我怎样才能正确地断言这一点?

Have you tried this only in child component您是否仅在子组件中尝试过此操作

@Input() data: Union;

Do not pass type while passing or calling child component传递或调用子组件时不要传递类型

<app-child1 [data]="data as Child1"> // not this
<app-child1 [data]="data"> // pass only data 

Feel free to point out any problems随时指出任何问题

// You can use this setter pattern, I use this
class ChildComponent {
    data: Child1;
    @Input() set( d: Union ) {
        data = d as unknown as Child1;
        // One problem is that you can slip the 'd' prop in the UNION type object from the parent but you can always use if statement to remedy that
    }
}

and in Parent并在父母

<app-child1 [data]="data">

You could just cast to any:您可以转换为任何:

<app-child1 [data]="$any(data)"></app-child1>
<app-child2 [data]="$any(data)"></app-child2>

Or cast to the expected type like this:或者像这样转换为预期的类型:

In your parent component:在您的父组件中:

asChildOne = (data: Union): Child1 => data as Child1;
asChildTwo = (data: Union): Child2 => data as Child2;

In the parent template:在父模板中:

<app-child1 [data]="asChildOne(data)"></app-child1>
<app-child2 [data]="asChildTwo(data)"></app-child2>

Or if you want to render the child only if the type is really the type it needs, you can do some type guards :或者,如果您只想在类型确实是它需要的类型时渲染孩子,您可以做一些类型保护

Somewhere near your interfaces:在您的界面附近的某个地方:

export function isCommon(obj: any): obj is Common {
  return obj && 'a' in obj && 'b' in obj;
}

export function isChild1(obj: any): obj is Child1 {
  return isCommon(obj) && 'c' in obj;
}

export function isChild2(obj: any): obj is Child2 {
  return isCommon(obj) && 'd' in obj;
}

In your parent component:在您的父组件中:

isChildOne = (data: Union): data is Child1 => isChild1(data)
isChildTwo = (data: Union): data is Child2 => isChild2(data)
asChildOne = (data: Union): Child1 => data as Child1;
asChildTwo = (data: Union): Child2 => data as Child2;

In the parent template:在父模板中:

<app-child1 *ngIf="isChildOne(data)" [data]="asChildOne(data)"></app-child1>
<app-child2 *ngIf="isChildTwo(data)" [data]="asChildTwo(data)"></app-child2>

You can simply use like this,你可以像这样简单地使用,

@Input() data: Child1 | Child2;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM