TypeScript:替换对象属性类型

时间:2018-11-27 14:31:29

标签: typescript

当我合并具有任意数量的键的两个对象,并且该合并中的属性类型被覆盖时。如何用打字稿表达这一点?

const a: {[propName: string]: string | number | boolean} = {
  a: 1,
  b: 2, 
  c: true
}

const b: {[propName: string]: string } = {
  c: "2"
}

const c: {[propName: string]: string | number } = { ...a, ...b };

即使c的类型签名正确,此示例也会显示打字稿错误。

2 个答案:

答案 0 :(得分:0)

如果像对stringa一样,显式地键入变量可以被b索引,则Typescript将不会跟踪在对象常量中分配的键(在无关紧要的是,该对象可以由任何字符串索引),因此它无法知道该属性将在扩展中被覆盖。

如果让编译器推断ab的类型,则所有功能将按预期工作:

const a = {
  a: 1,
  b: 2, 
  c: true
}

const b = {
  c: "2"
}

const c: {[propName: string]: string | number } = { ...a, ...b }; // ok now since the compiler knows that `c` in `a` will be overwritten

如果要定义受另一种类型约束的对象文字(例如,在这里,它们受索引签名的约束),但是还希望保留对象文字的实际类型,则可以使用函数来实现这个:

function constrain<T>() {
    return function <U extends T>(o: U) {
        return o
    }
}
const a = constrain<{ [propName: string]: string | number| boolean }>()({
    a: 1,
    b: 2, 
    c: true
})

const b = constrain<{ [propName: string]: string  }>()({
    c: "2"
})

const c: {[propName: string]: string | number } = { ...a, ...b };

答案 1 :(得分:0)

如果您需要在打字稿中合并对象,则可以使用lodash

var object = {
  'a': [{ 'b': 2 }, { 'd': 4 }]
};

var other = {
  'a': [{ 'c': 3 }, { 'e': 5 }]
};

_.merge(object, other);

// Output:
// { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }