面试题:请问typescript如何做到对象合并的类型推导?

只是小丑
  • 36

实现两个对象部分属性的合并,比如说t,s两个对象,当s中有t不存在的属性时给t加上s的属性并赋值。要求不更改t的引用地址。方法如下

const merge = (target, source)=> {
for (const key in source) {
        if (typeof target[key] === 'undefined') {
            target[key] = source[key];
        }
    }
    return target;
}

补充1个测试案例

const a = { name: undefined, age: 2 };
const b = { name: '小明', weigth: 100 };
const c = merge(a,b)
console.log(a)  // { name: '小明', age: 2,weigth: 100 }
console.log(c)  // { name: '小明', age: 2,weigth: 100 }
回复
阅读 1.2k
4 个回答
import typePredicates from 'ts-type-predicates';

const merge = (target, source) =>
{
    for (const key in source)
    {
        if (target[key] === 'undefined')
        {
            target[key] = source[key];
        }
    }
    return target;
}

const a = {
    name: '小明',
    age: 18,
}
const b = {
    age: '18',
    weight: 100,
}

typePredicates<typeof a & Omit<typeof b, keyof typeof a>>(a, () => merge(a, b))

console.log(a.weight)

类型上的合并只需要使用 & 即可

function merge<T, R>(a: T, b: R): T & R {
    return 0 as unknown as any
}

const c = merge({ a: 1 }, { b: 1 })

c.a + c.b

还有一种方法可以兼具类型与效果

const d = { ...{ a: 1 }, ...{ b: 1 } }

ts play

type A = {
  a: number;
  b: string;
}
type B = {
  a: string;
  c: boolean;
}

type E<A, B> =  A & Omit<B, keyof A>;
type S = E<A, B>;

const m: S = {
  a: 1,
  b: '',
  c: false
}

这样?

不就是A&B的事情嘛,有那么复杂吗

type MergeObject = {
    [key in string | number]: any
}

// 只是写法这样看着顺眼
type Target<A, B> = A & Omit<Partial<B>, keyof A>

// type Merge<A, B> = {
//     [P in keyof A]: A[P]
// } & {
//     [P in keyof B]: B[P]
// }
type Merge<A, B> = A & B

function merge<A extends MergeObject, B extends MergeObject>(target: A, source: B): Merge<A, B> {
    for (const key in source) {
        if (typeof target[key] === 'undefined') {
            (target[key] as Target<A, B>) = source[key]
        }
    }
    return target as Merge<A, B>
}

const a = {
    name: '小明',
    age: 18
}
const b = {
    weight: 100
}
const person = merge(a, b)
console.log(a == person, person)

const abc = {
    history: {
        finish: false
    }
}
const t = {
    history: {}
}
const mergeABC = merge(abc, t)
console.log(abc == mergeABC, mergeABC)
你知道吗?

宣传栏