交集两个对象属性

huangapple go评论57阅读模式
英文:

intersection two object properties

问题

我有两个对象DomElement和textElement。
DomElement有5个属性,textElement有其中的2个属性(用作类型)。
我想要使用最高效的解决方案将这两个属性添加到textElement。

我遍历DomElement,但这里我的第一个问题是我无法获取DomElement类型的键以进行比较或遍历。

类型DomType = {
backgroundColor?:字符串,
color?:字符串,
padding?:字符串,
margin?:字符串,
display?:字符串,
}

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

类型TextType = {
backgroundColor?:字符串,
color?:字符串,
}

let textElement:TextType = {};

对于让键位于DomElement中的键,
我不能将DomElement的键与TextType的键进行比较。

textElement [key] = DomElement [key]

期望的输出{backgroundColor: red, color: green}

英文:

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}

答案1

得分: 1

一个问题是 key in ... 返回字符串,因为即使你为对象定义了类型,它仍然可以具有更多的属性,这是 TypeScript 工作的方式。

所以你可以获取键并将它们转换为该类型的 keyof

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

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

或者你可以明确地手动复制键。

你可以在这个问题中阅读更多信息 https://github.com/Microsoft/TypeScript/issues/12870

希望能作为一个起点有所帮助。

英文:

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.

答案2

得分: 1

你有几个问题。首先,你尝试循环遍历DomElement的属性,但实际上你只想复制两个属性。所以更有意义的是只循环遍历这两个属性。

其次,你在运行时没有任何关于这些属性的列表。你定义了一个声明了这两个属性的type,但TS类型只存在于编译时。在运行时,我们只有JS对象。

第三,你正在获取字符串属性名称,所以TS不知道它们是什么,并拒绝将它们用于从对象中获取值(除非你将对象声明为any类型)。

一个选择是更改你的类型声明,不使用?来允许属性被省略,而是使用string | undefined,这样你仍然可以将属性设置为未定义,但你必须在该类型的任何对象中包含它们:

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

let textElement: TextType = {
    // TS强制你声明这些属性
    backgroundColor: undefined,
    color: undefined,
};

这样做的好处是现在你在运行时有一个具有两个属性的textElement,你可以循环遍历它们。

下一个问题是获得经过良好类型化的属性键。我喜欢这个简单的助手函数:

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

它不一定准确,因为obj可能是T的子类型,并且具有未包括在T中的额外属性。但在没有子类型的简单情况下,它可以工作。

// 注意:使用for...of,而不是for...in!
for (let key of keysOf(textElement)) {    
    textElement[key] = DomElement[key];
}

console.log(textElement);

输出:

{ backgroundColor: 'red', color: 'green' }
英文:

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&lt;T extends object&gt;(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: &#39;red&#39;, color: &#39;green&#39; }

huangapple
  • 本文由 发表于 2023年4月17日 02:35:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76029658.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定