假设我们有
x = {a:65, b:634, c:74};
y = {o:453, e:5342, g:543}
z = {o:453, e:5342, b:543}
// Doing this should be okay
const both = {...x, ...y}
// However, when doing this:
const both = {...x, ...z}
我需要它显示一些错误,例如“属性 b 无法重新分配”或其他什么,只是不要让它编译。有什么建议吗?
编辑: 我知道我可以轻松编写一个函数来组合对象并有条件地引发异常,但重点是我需要在运行时之前进行此类检查。如果可以使用 typescript、eslint 或任何可以在运行前检查此类条件的技巧来完成,那将非常有帮助......
最简单的方法是制作一个简单的实用函数..
您可以获取每个键的键,并使用 include 来确保该键不存在于其他键中。
例如。
const x = {a:65, b:634, c:74};
const y = {o:453, e:5342, g:543};
const z = {o:453, e:5342, b:543};
function join(a,b) {
const ak = Object.keys(a);
const bk = Object.keys(b);
for (const k of bk)
if (ak.includes(k))
throw new Error(`key ${k} cannot be re-assigned`);
return {...a, ...b};
}
console.log(join(x, y));
console.log(join(x, z));
如果您希望使用 Typescript 在设计时进行一些检查,一个想法是获取两个对象的交集类型,如果交集从不存在,那么我们可以创建一个假类型,该类型返回 true,如果重叠则返回 false。 如果您随后尝试将 true 分配给该类型并且存在重叠,您将收到错误。 好的捆绑器上的假分配也应该删除这个假声明。
例如。
const x = {a:65, b:634, c:74};
const y = {o:453, e:5342, g:543};
const z = {o:453, e:5342, b:543};
type NoOverlap<A extends object, B extends object> =
keyof A & keyof B extends never ? true : false;
const _dummy1:NoOverlap<typeof x, typeof y> = true;
const _dummy2:NoOverlap<typeof x, typeof z> = true; //this will error.
这是一个有 n 个参数的解决方案:
function combineNoOverwrite(...args) {
return args.reduce((acc, cur) => {
for (var key in cur) {
if (cur.hasOwnProperty(key) && !acc.hasOwnProperty(key)) {
acc[key] = cur[key];
} else {
throw new Error(`key ${key} cannot be re-assigned`);
}
}
return acc;
});
}
您可以使用以下内容。
function combine(x, y) {
const array = Object.keys(x).concat(Object.keys(y))
if (array.length != [...new Set(array)].length) {
console.error("Error: Duplicate Key")
return
}
return {...x, ...y}
}
这可以仅使用 Typescript 来完成,并且可以扩展到任意数量的跨度。
/**
* Given a tuple of interfaces, this resolves immediately to the duplicate keys
* of the first offending item in the tuple. If there are no offending members
* in the tuple, this resolves to 'never'.
*/
type SomeDuplicateKeys<T extends Object[]> = T extends [
infer H1 extends Object,
infer H2 extends Object,
...infer R extends Object[],
]
? keyof H1 & keyof H2 extends never
? SomeDuplicateKeys<[H1 & H2, ...R]>
: keyof H1 & keyof H2
: never;
type UnionNoDuplicateKeysAllowed<T extends Object[]> =
SomeDuplicateKeys<T> extends never ? T[number] : never;
const x = { a: 65, b: 634, c: 74 };
const y = { o: 453, e: 5342, g: 543 };
const z = { o: 453, e: 5342, b: 543 };
// Okay.
const foo: UnionNoDuplicateKeysAllowed<[typeof x, typeof y]> = { ...x, ...y };
// Error: Type '{ o: number; e: number; b: number; a: number; c: number; }' is not assignable to type 'never'. (2322)
const bar: UnionNoDuplicateKeysAllowed<[typeof x, typeof z]> = { ...x, ...z };