Issue
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;
}
Solution
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;
}
Answered By - BreenDeen
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.