简体   繁体   中英

Error in *ngFor with KeyValuePipe: ngtsc(2322)

I have the following types

type ParentKeys = "mum" | "dad";
type ChildKeys = "alice" | "frank";

type Parents = {
    [parentKey in ParentKeys]: {
        children: {
            [childKey in ChildKeys]: {
                parent: parentKey;
                key: childKey;
            };
        }[ChildKeys][];
    };
};

That is, the inner child objects { parent, key } are mounted inside a tree structure, below their resp. parents; all parent-child pairings are allowed. For an example check

const parents: Parents = {
    mum: {
        children: [
            { parent: "mum", key: "alice", },
        ],
    },
    dad: {
        children: [
            { parent: "dad", key: "frank", },
            { parent: "dad", key: "alice", },
        ],
    },
};

Now, if I'm using parents inside an Angular template

<div *ngFor="let parent of parents | keyvalue">
    <div *ngFor="let child of parent.value.children">
        <div>child {{child.key}} of parent {{child.parent}}</div>
    </div>
</div>

I get the error

Type
'(
    { parent: "mum"; key: "alice"; } |
    { parent: "mum"; key: "frank"; }
)[] |
(
    { parent: "dad"; key: "alice"; } |
    { parent: "dad"; key: "frank"; }
)[]'
is not assignable to type
'(
    (
        { parent: "mum"; key: "alice"; } |
        { parent: "mum"; key: "frank"; }
    )[] &
    NgIterable<
        { parent: "mum"; key: "alice"; } |
        { parent: "mum"; key: "frank"; }
    >
) | null | undefined'
.ngtsc(2322)

Of course this can be resolved using $any() , but obviously something is wrong with my types, or with the KeyValuePipe .

The issue is related to the typing done in parents, the following should work:
 type Parents = { [parentKey in ParentKeys]: { children: { parent: ParentKeys, key: ChildKeys }[]; }; };

The issue was an over-complication in the typing of the children object.

The issue lies in own the keyvalue pipe interacts with the *ngFor .

The following html works:

 <div *ngFor="let parent of parents | keyvalue"> <div *ngFor="let child of parents[parent.key].children"> <div>child {{ child.key }} of parent {{ child.parent }}</div> </div> </div>

The main different is that instead of us calling parent.value , we call parents[parent.key] . Doing so means we obtain the value stored in the original object. This is because the keyvalue combined with the *ngFor modifies the object, causing it to lose its iterability and raising an error.

simply change it like this

type Parents = {
  [parentKey in ParentKeys]: {
    children: Array<{
      parent: ParentKeys;
      key: ChildKeys;
    }>;
  };
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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