如何在打字稿中组合对象属性?

Posted

技术标签:

【中文标题】如何在打字稿中组合对象属性?【英文标题】:How to combine object properties in typescript? 【发布时间】:2016-08-30 18:27:58 【问题描述】:

我想知道最好的方法,比如我有两个对象

var objectA = 
    propertyA: 1,
    propertyB: 2
    ...
    propertyM: 13


var objectB = 
    propertyN: 14,
    propertyO: 15
    ...
    propertyZ: 26

如果objectC是由

创建的
var objectC = Object.assign(objectA, objectB);

如何声明/描述 objectC,以便编译器/IDE 知道它同时具有 objectA 和 objectB 的属性?

我想找到一种不需要为 objectA 和 objectB 定义接口的方法。我不想为同一个属性写两次声明和定义/评估。如果我在一个对象上有太多属性,这种冗余就很重要。

(有没有可以提取现有对象的接口/类型的算子?)

有可能吗?

【问题讨论】:

【参考方案1】:

似乎这样可以解决问题:

var objectA = 
    propertyA: 1,
    propertyB: 2,
    .
    . // more properties here
    .
    propertyM: 13
;

var objectB = 
    propertyN: 14,
    propertyO: 15,
    .
    . // more properties here
    .
    propertyZ: 26
;

var objectC = ...objectA, ...objectB; // this is the answer

var a = objectC.propertyA;

var n = objectC.propertyN;

根据这篇文章:https://blog.mariusschulz.com/2016/12/23/typescript-2-1-object-rest-and-spread


此外,分解中变量的顺序很重要。 考虑以下几点:

var objectA = 
    propertyA: 1,
    propertyB: 2, // same property exists in objectB
    propertyC: 3
;

var objectB = 
    propertyX: 'a',
    propertyB: 'b', // same property exists in objectA
    propertyZ: 'c'
;

// objectB will override existing properties, with the same name,
// from the decomposition of objectA
var objectC = ...objectA, ...objectB; 

// result: 'b'
console.log(objectC.propertyB); 

// objectA will override existing properties, with the same name,
// from the decomposition of objectB
var objectD = ...objectB, ...objectA; 

// result: '2'
console.log(objectD.propertyB); 

【讨论】:

只是为了改进答案:这一行可以解决问题: var objectC = ...objectA, ...objectB; 如果两个对象中存在相同的键,我想更新 objectA 的属性。意味着如果键相同,那么它应该具有objectB的属性。这怎么可能? 阅读我的回答中的 cmets。基本上,它从左到右构造属性,其中每个新信息都会覆盖现有信息:var objectC = ...objectA, ...objectB;。如果属性名称相同,objectB 中的属性将覆盖已经从objectA 分配的属性。 这行得通,因此回答了 OP,但是我担心现在没有与 objectD 或 objectC 关联的类型,当您尝试将其显式键入某些东西时(假设有这样的类型),它不会工作。有类型安全的方法吗? @SrivathsaHarishVenkataramana 类型是从分配中推断出来的。所以 objectC 将有propertyB: string,而 objectD 将推断它为propertyB: number。您可以手动输入 C 和 D:type ABC = propertyA: number; propertyB: string | number; propertyC: number; propertyX: string; propertyZ: string; 或通过将 propertyB 设置为字符串或数字来仅输入其中之一。【参考方案2】:

所以编译器/IDE 知道它同时具有 objectA 和 objectB 的属性?

使用交集类型 + 泛型。例如。 from here

/**
 * Quick and dirty shallow extend
 */
export function extend<A>(a: A): A;
export function extend<A, B>(a: A, b: B): A & B;
export function extend<A, B, C>(a: A, b: B, c: C): A & B & C;
export function extend<A, B, C, D>(a: A, b: B, c: C, d: D): A & B & C & D;
export function extend(...args: any[]): any 
    const newObj = ;
    for (const obj of args) 
        for (const key in obj) 
            //copy all the fields
            newObj[key] = obj[key];
        
    
    return newObj;
;

更多

这里都提到了:https://basarat.gitbooks.io/typescript/content/docs/types/type-system.html

【讨论】:

谢谢。这似乎有效。但是,extend() 函数是在第 3 方库中定义的,有没有办法在其 d.ts 文件中覆盖 extend() 的这个特定定义? (我正在使用下划线 _.extend() )。 是的。只需修改underscore.d.ts【参考方案3】:

(是否有可以提取接口/类型的运算符 现有对象?有可能吗?)

你应该选择typeof

type typeA = typeof objectA;
type typeB = typeof objectB;

要使它们合并,您可以使用 basarat 已经指出的交集操作。

type typeC = typeA & typeB

【讨论】:

【参考方案4】:

使用Typescript spread operator 转译为javascript Object.assign()

如果您需要深度树对象合并,您可以使用 best-global 包的更改功能

【讨论】:

【参考方案5】:

试试这个..

const person =  name: 'TRilok', gender: 'Male' ;
const tools =  computer: 'Mac', editor: 'Atom' ;
const attributes =  handsomeness: 'Extreme', hair: 'Brown', eyes: 'Blue' ;

const summary = ...person, ...tools, ...attributes;

【讨论】:

【参考方案6】:

Lodash 有一个“扩展”功能,可以组合对象并让 Typescirpt 知道新对象具有您期望的类型。

const a =  one: 1, two: 2 ;
const b =  three: 3, four: 4 ;
const c = lodash.extend(a, b);
// c:  one: 1, two: 2, three: 3, four: 4 

【讨论】:

以上是关于如何在打字稿中组合对象属性?的主要内容,如果未能解决你的问题,请参考以下文章

如何理解打字稿中的“属性'名称'在'用户'类型中是私有的”

我将如何在打字稿中定义这个对象?

如何在打字稿中验证输入标签的类型“target.dataset”属性

如何在打字稿中过滤对象数组

我们如何在打字稿中获得嵌套对象类型

如何故意在打字稿中定义一个“空接口”