1

How do I rewrite the code to get rid of explicit casts?

type A={a:number};
type B={b:string};


let a:A={a:0};
let b:B={b:''};

function arrayToObject<T>(array:T[]):T {
    return array.reduce((r,c) =>Object.assign(r,c))
}

let result = arrayToObject([a,b]);//expects A&B instead A|B

2 Answers 2

1

Unfortunately there is no way to convert a union type into an intersection type. This is also evident by the way Object.assign is defined:

assign<T, U>(target: T, source: U): T & U;  
assign<T, U, V>(target: T, source1: U, source2: V): T & U & V;
assign<T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W;
assign(target: object, ...sources: any[]): any;

lib.d.ts provides several strongly typed versions for up to 3 sources, and for more sources just becomes an array of any with no type safety.

You could use a similar approach:

// Public signatures 
function arrayToObject<T>(array:[T]):T
function arrayToObject<T, T2>(array:[T, T2]):T & T2
function arrayToObject<T, T2, T3>(array:[T, T2, T3]):T & T2 & T3
function arrayToObject<T, T2, T3, T4>(array:[T, T2, T3, T4]):T & T2 & T3 & T4
function arrayToObject<T>(array:T[]):T // for more or dynamic values
// Implementation signature
function arrayToObject<T>(array:T[]):T {
    return array.reduce((r,c) =>Object.assign(r,c))
}
Sign up to request clarification or add additional context in comments.

Comments

0

Basically the problem is that reduce has the type: (T, T): T which causes Object.assign to believe that it also has the type (T, T): T.

So the problem is that you want to do this for an arbitrary length array, if you instead had a distinct number of elements in the array you could unwrap the loop and use the form ``Òbject.assign(A, B): A&B```.

But what you want is probably not possible in Typescript since you need to create a type for the result of the function which is the intersection type of an arbitrary array of union type. If you could declare such a type you could then just replace reduce with a loop.

Comments

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.