Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

intersection two object properties

Tags:

typescript

I have two objects DomElement, textElement. DomElement has 5 properties, textElement 2 of it (used as a type) I want to use most efficient solution to add these two properties to textElement.

I iterate through DomElement but here my first problem I can't get keys of type DomElement to compare or iterate.

type DomType = {
    backgroundColor?: string,
    color?: string,
    padding?: string,
    margin?: string,
    display?: string,
}

let DomElement: DomType = {
    backgroundColor: 'red',
    color: 'green',
    padding: '5px',
    margin: '2px',
    display: 'flex'
}

type TextType = {
backgroundColor?: string
color?: string,
}

let textElement: TextType = {};

for (let key in DomElement) {
console.log(key in textElement)
// can't compare DomElement keys with TextType keys
textElement[key] = DomElement[key]
}

console.log(textElement);
// desired output {backgroundColor: red, color: green}
like image 310
Lex Avatar asked Mar 09 '26 18:03

Lex


2 Answers

You have several issues here. First, you are trying to loop through the properties of DomElement, which will visit five properties, when in fact you only want to copy two properties. So it would make a lot more sense to loop through just those two properties.

Second, you don't have a list anywhere at runtime of what those properties are. You define a type that states the two properties, but TS types only exist at compile time. At runtime, all we have is just JS objects.

And third, you are getting string property names, so TS doesn't know what they are and refuses to use them to fetch values from objects (unless you declare the objects as type any).

One option would be to change your type declaration to not use ? which allows properties to be omitted, and instead use string | undefined, so you can still make the properties undefined but you must include them in any object of this type:

type TextType = {
    backgroundColor: string | undefined;
    color: string | undefined;
};

let textElement: TextType = {
    // TS forces you to declare thes
    backgroundColor: undefined,
    color: undefined,
};

The advantage of this is that now you have a textElement with two properties at runtime which you can loop through.

The next problem is getting well-typed property keys. I like this simple helper:

export function keysOf<T extends object>(obj: T) {
    return Object.keys(obj) as (keyof T)[];
}

It's not generally accurate because obj may be a subtype of T and have extra properties not included in keyof T. But in simple scenarios with no subtyping it works.

// Note: for...of, not for...in!
for (let key of keysOf(textElement)) {    
    textElement[key] = DomElement[key];
}

console.log(textElement);

Output:

{ backgroundColor: 'red', color: 'green' }
like image 72
Daniel Earwicker Avatar answered Mar 11 '26 17:03

Daniel Earwicker


one issue is key in ... returns string because even if you have a type for your object its could technically have more properties, that's just how typescript works.

So you can either get the keys and cast them to be keyof that type.

const keys = Object.keys(DomElement) as (keyof TextType)[]

keys.forEach(key=>{
  textElement[key]=DomElement[key]
})

Or you can be explicit and manually copy the keys.

You can read something in this issue https://github.com/Microsoft/TypeScript/issues/12870

Hope it helps as a starting point.

like image 42
Max Avatar answered Mar 11 '26 17:03

Max



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!