Javascript map function not working as expected

Viewed 79

I have a simple class which creates classes from JSON objects. Here are the types. When I call map on the destructured SNode, it complains that an array of ANode [] is not assignable to ANode | BNode. My expectation is the map takes each object from the objects in the destructured children ANode array so I did not expect this error. Can someone explain why this is happening? When I hover over the { children } = snode in the IDE, it shows me that children is an array of ANode[], so why is map not passing individual ANodes? My goal is to be able to return a specific type when getClass determines the type of node passed in. As I am new to Typescript, I don't know how to do that to accomplish my goal.

interface ANode {
  id: string;
  value: string;
}

interface BNode {
  id: string;
  value: string;
}

interface SNode {
  sid: string;
  children: Array<ANode>;
}

function isSNode(node: any): node is SNode {
  return node && "sid" in node;
}

class SObject {
  constructor(public children: Map<string, ANode>) {}
}
type ValidNode = ANode | BNode;

function getClass(node: ValidNode): SObject {
  if (isSNode(node)) {
    return createSNodeClass(node);
  }
}

function createSNodeClass(snode: SNode): SObject {
  const { children = [] } = snode;
  return new SObject(toMap(children.map(getClass))); //
  //Error
  //SNode [] is not assignable to getClass of ANode | BNode
}

function toMap(nodes: ANode[]) {
  const m = new Map<string, ANode>();
  for (const node of nodes) {
    m.set(node.id, node);
  }
  return m;
}
1 Answers
class ANode {
  constructor(
  public id: string,
  public value: string,){}
}

class BNode {
   constructor(
   public id: string,
   public value: string,){}
}

class SNode{
   constructor(
     public sid: string,
     public children: Array<ANode>,){}
 }

  function isSNode(node:any): node is SNode{
   return node && node instanceof SNode;
  }

 function isANode(node:any): node is ANode{
   return node &&  node instanceof ANode;
 }

function isBNode(node:any): node is BNode{
  return node && node instanceof BNode;
 }

 class SObject {
   constructor(
    public children: ANodeClass[]
   ){}
  }
   
   type ValidNode = ANode | BNode | SNode 

   type FinalOutput = ANodeClass | BNodeClass | SObject
  

   class ANodeClass {
     constructor(   
        public node: ANode){
        this.id = node.id;
        this.value = node.value;
    }
          id: string;
         value: string;
   }

   class BNodeClass {
     constructor(
     public node: BNode){}
       id: string;
       value: string;
   }
  
   function getClass(node: ValidNode): FinalOutput | undefined{
      if(isSNode(node)){
        return createSNodeClass(node)
      }else if(isANode(node)){
          return new ANodeClass(node) 
      }else if(isBNode(node)){
          return new BNodeClass(node) 
      }else{
          throw new Error('Not Allowed type');
      }
   }

   function createSNodeClass(snode:SNode): SObject{
      const {children = []} = snode;
      return new SObject(children.map(node =>            
        getClass(node) as ANodeClass            
        )); 
   }

   

   

    function toMap(nodes: ANodeClass []){
       const m = new Map<string, ANodeClass>();
       for(const node of nodes){
           m.set(node.id, node);
       }
       return m;
     }
Related