1

I am looking for a way of a "mapped" object type in typescript.

I have a the following typings:

interface Factory<T>{
     serialize: (val: T)=>void,
     deserialize: ()=>T,
}
interface MyDict{
     [key: string]: Factory<any>
}

function deserialize(dict: MyDict){
     let mapped = {};
     for(let k in dict){
          mapped[k] = dict[k].deserialize();
     }
     return mapped;
}

What I want is that the return type of map is correctly determined.

So when doing this:

let mapped = map({
    foo: {deserialize: ()=>'hello world'}, 
    foo2: {deserialize: ()=>123}, 
    foo3: {deserialize: ()=>({foo4: 'foo4'})}
});

mapped should be typed as {foo: string, foo2: number, foo3: {foo4: string}}.

1
  • Given MyDict is not generic (and map is not generic either) - it's unlikely you can have that. Commented Mar 13, 2020 at 20:29

1 Answer 1

2

You can do this using a mapped type. The function will also need to be generic in order to capture the actual type of the argument:

interface Factory<T>{
     serialize?: (val: T)=>void,
     deserialize: ()=>T,
}
interface MyDict{
     [key: string]: Factory<any>
}

type FactoryReturnType<T extends MyDict> = {
    [K in keyof T]: ReturnType<T[K]['deserialize']>
}

function deserialize<T extends MyDict>(dict: T){
     let mapped = {} as FactoryReturnType<T>;;
     for(let k in dict){
          mapped[k] = dict[k].deserialize();
     }
     return mapped;
}

let mapped = deserialize({
    foo: {deserialize: ()=>'hello world'}, 
    foo2: {deserialize: ()=>123}, 
    foo3: {deserialize: ()=>({foo4: 'foo4'})}
});

mapped.foo3.foo4

Playground Link

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

3 Comments

This almost seems to be the solution. However I had a bit of an unclear part in my question. Instead of just a "factory" function, I actually have a generic Interface with multiple properties derived from <T>, the factory or in my case deserialize function is just one of them. I updated my example accordingly.
@LucaAdrian updated the answer. Sorry the initial code was not 100% consistent between call and definition so I took some decistions.
Already tried that, just made a typo, but works wonderfully now ^^. So thanks a lot.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.