1

I have a JSON array of serialized objects that each have a type field. I'm trying to deserialize them but can't get TS to play along:

ts playground link

type serializedA = { type: 'A', aProp: string };
class A {
    public type = 'A';
    constructor(data: serializedA) {}
}

type serializedB = { type: 'B', bProp: string };
class B {
    public type = 'B'
    constructor(data: serializedB) {}
}

const classMap = { A, B };

function deserialize(serializedObject: serializedA | serializedB) {
    const Klass = classMap[serializedObject.type];
    new Klass(serializedObject);
}

The issue is that last line. TS doesn't know that Klass and serializedObject are now either both A or both B, and I'm having trouble figuring out how to tell it that.

1
  • The issue is that the construct signature of Klass is new (serializedA & serlializedB) => A | B which reduces to new (never) => A | B since the type {type: 'A' & 'B', aProp: string, bProp: string} must be empty. This is definitely annoying since you know better, but you have to either use a type assertion or write a series of tests that narrow the type to its individual possibilities. Commented Sep 15, 2020 at 22:59

2 Answers 2

1

For production grade decoding libraries, take a look at following:

we are using io-ts extensively. You can refer it here

Sign up to request clarification or add additional context in comments.

1 Comment

I would second io-ts as an excellent option for this. We also use it exclusively
0
type serializedA = { type: 'A', aProp: string };
class A {
    public type='A';
    constructor(data: serializedA) {}
}

type serializedB = { type: 'B', bProp: string };
class B {
    public type ='B'
    constructor(data: serializedB) {}
}

const classMap = { A, B };

function deserialize(serializedObject: serializedA | serializedB) {
    if(serializedObject.type === "A"){
        let Klass = classMap[serializedObject.type]
        return new Klass(serializedObject);
    } else {
        let Klass = classMap[serializedObject.type]
        return new Klass(serializedObject);
    }
}

1 Comment

Yeah, I'm trying to avoid that ;) There are about 50 different classes and I don't like writing super verbose code just to make TS happy

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.