【问题标题】:Typescriping keyof object with 1 property issue使用 1 个属性问题键入 keyof 对象
【发布时间】:2021-11-15 16:53:18
【问题描述】:

所以我创建了一个合并函数,它接收一个对象和另一个对象对象的键。然后该函数返回合并的对象,如下所示。

const data = {
    end: 'World'
}

const working = {
    test: 'Worked'
}

const map = {
    data,
    working
}

export type Map = typeof map;

export type Keys = keyof Map;

function merge<A, B extends Keys, C extends Map[B] & A>(input: {
    obj: A;
    append?: B;
}) {

    const append = input.append ? map[input.append] : {};

    return {
        ...input.obj,
        ...append
    } as C
}

现在,当 map 对象具有 > 1 个属性时,它可以正常工作。又名

const initial = {
    start: 'Hello'
}

const a = merge({
    obj: initial,
    append: 'data'
);

const b = merge({
    obj: initial
});

// Available as expected
console.log(a.end);

// Errors as expected
console.log(b.end);

但是,如果我将 map 对象更改为只有 1 个这样的属性

const map = {
    data
}

然后发生这种情况

const a = merge({
    obj: initial,
    append: 'data'
);

const b = merge({
    obj: initial
});

// Available as expected
console.log(a.end);

// Available but outputs undefined
console.log(b.end);

我有点明白发生了什么。当 map 对象只有 1 个属性时,泛型默认为该键,因此 TypeScript 认为对象已合并,但实际上并非如此。

如何避免这种情况?

【问题讨论】:

  • 它返回undefined,因为当input.appendundefined 时你没有附加任何东西
  • 不是这样,map[input.append] 永远不能未定义,因为传递的类型 必须map 的键。所以如果input.append不是未定义的,那么它肯定是keyof map,否则append是一个空对象。我找到了解决方案,并将其作为答案发布。

标签: javascript typescript object deno


【解决方案1】:
export type Map = typeof map;

export type Keys = keyof Map;

function merge<A, B extends C extends keyof Map ? A & Map[C] : A, C extends undefined | keyof Map = undefined>(input: {
    obj: A;
    append?: C;
}) {

    const append = input.append ? map[input.append as keyof Map] : {};

    return {
        ...input.obj,
        ...append
    } as B
}

const data = {
    end: 'World'
}

const map = {
    data
}

// Testing

const start = {
    hello: 'World'
}

const a = merge({
    obj: start
});

// Outputs as expected
console.log(`${a.hello} World`);

// Errors as expected
console.log(`${a.hello} ${a.end}`);

const b = merge({
    obj: start,
    append: 'data'
})

// Outputs as expected
console.log(`${b.hello} ${b.end}`);

这就是我的工作方式。

基本上C 扩展undefined | keyof Map 并具有undefined 的默认类型,因此默认情况下返回的类型是A &amp; undefined。当 必须 keyof Map 的值作为附加值传递时,C 成为该类型,因此返回的类型为 Map[C] &amp; A

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-28
    • 1970-01-01
    • 2019-12-06
    • 2014-02-28
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    相关资源
    最近更新 更多