Typescript 如何使用可选键(而不是部分键)从现有类型定义类型?

Typescript 如何使用可选键(而不是部分键)从现有类型定义类型?,typescript,Typescript,我正在React/Redux中进行一些状态合并,包括: const newstatesicle={ …state.activeData.entities[action.payload.localId], …action.payload, isModified:正确 } 我的问题是,我想定义action.payload的类型,使其与state.activeData.entities的成员具有相同的确切类型,但所有道具都是可选的(localId除外),这样我就可以合并我要更改的键,并保持其余键不变

我正在React/Redux中进行一些状态合并,包括:

const newstatesicle={
…state.activeData.entities[action.payload.localId],
…action.payload,
isModified:正确
}
我的问题是,我想定义action.payload的类型,使其与state.activeData.entities的成员具有相同的确切类型,但所有道具都是可选的(localId除外),这样我就可以合并我要更改的键,并保持其余键不变

让我们将此基本类型称为“实体”,并假设以下结构:

接口实体{
本地化:数字
a:字符串
b:编号|未定义
c:日期
}
我想得到的是:

interface PartialEntity{
    localId: number
    a?: string
    b?: number | undefined
    c?: Date
}
我尝试了以下方法:

type PartialEntity=Partial&{localId:number}
这对我不起作用的原因是,Partial允许键具有未定义的值(我不想允许),因此结果类型为:

type PartialEntity{
    localId: number,
    a?: string | undefined,
    b?: number | undefined,
    c?: Date | undefined
}
当然,我可以手动写出来,但我需要为每个实体写出来,将来可能还会写,而且不是很干。。。有没有像Partial这样的操作符,可以满足我的要求

编辑:原来“c?:Date | undefined”和“c?:Date”是等效的,但我真正想要的是typeScript允许不设置键,但如果设置为undefined,则会抛出一个错误,因为undefined仍然会在我展开这样的对象时覆盖我的现有值:

const a = {prop_a: 1, prop_b: 2}
const b = {prop_a: undefined, prop_b: 3}
const c = {...a, ...b};
c现在是:

{
    prop_a: undefined,
    prop_b: 3
}

您已经发现,TypeScript并不能很好地区分缺少的属性与存在的属性之间的差异,但其值是
未定义的属性。从仅仅读取其中一个属性的角度来看,实际上没有什么区别
foo.bar===未定义
在任何一种情况下都将为
true
。但是,当然,在某些情况下会有明显的差异,例如当您展开一个对象时,或者甚至是像foo中的
“bar”这样的简单测试。TypeScript类型系统和Javascript行为之间的这种不匹配是一个长期存在的问题;请参阅,以进行长时间的讨论。如果你想看到这个地址,你可以给它一个你已经发现TypeScript并不能很好地分辨一个属性和一个属性之间的区别,这个属性缺失,但是它的值是
未定义的。从仅仅读取其中一个属性的角度来看,实际上没有什么区别
foo.bar===未定义
在任何一种情况下都将为
true
。但是,当然,在某些情况下会有明显的差异,例如当您展开一个对象时,或者甚至是像foo中的
“bar”这样的简单测试。TypeScript类型系统和Javascript行为之间的这种不匹配是一个长期存在的问题;请参阅,以进行长时间的讨论。如果你想看到这个地址,你可以给它一个“…并且不允许省略那些键…”是的,它是:(但它确实允许
未定义的
)是的,我只是通过修修补补发现了这一点,但它允许undefined这一事实仍然使它成为我的交易破坏者,因为意外地传递undefined会覆盖现有的值。将编辑问题。我认为您需要进行运行时检查。即使是手动编写的带有(比如)
a?:string
的类型也允许
{a:undefined}
:是否满足您的需要?如果是这样,我会写一个关于它是如何工作的答案。如果没有,你能详细说明我遗漏了什么吗?我可能会写一个答案来解释这一切,但如果你认为我在某种程度上不理解这个问题,请让我知道。“…并且不允许省略这些键…”是的,它允许:(但它确实允许
未定义的
)是的,我只是通过修修补补发现了这一点,但它允许undefined这一事实仍然使它成为我的交易破坏者,因为意外地传递undefined会覆盖现有的值。将编辑问题。我认为您需要进行运行时检查。即使是手动编写的带有(比如)
a?:string
的类型也允许
{a:undefined}
:是否满足您的需要?如果是这样,我会写一个关于它是如何工作的答案。如果没有,你能详细说明我遗漏了什么吗?我可能会写一个答案来解释这一切,但如果你认为我在某种程度上不理解这个问题,请让我知道。谢谢你写得非常好的答案@T.J.Crowder我假设他们谈论的是我遇到的同一个问题(正如我在文章中解释的),当你将两个具有一些共享属性的对象分解为一个时,如果第二个对象缺少第一个对象的属性,该属性将不会被覆盖,但是如果第二个对象的属性设置为未定义,即使结果对象在第一个对象中具有不同的值,也会将其作为未定义对象@Supperhero-这不是破坏,而是传播。这是解构:(但你很可能是对的,spread确实从对象中提取属性…)噢,我是说spread而不是destructure。很抱歉是啊,把我的话搞错了,我的错。我会修改这个问题,让它更清楚。谢谢你写得很好的答案@T.J.Crowder我假设他们谈论的是我遇到的同一个问题(正如我在文章中解释的),当你将两个具有一些共享属性的对象分解为一个时,如果第二个对象缺少第一个对象的属性,该属性将不会被覆盖,但是如果第二个对象的属性设置为未定义,即使结果对象在第一个对象中具有不同的值,也会将其作为未定义对象@Supperhero-这不是破坏,而是传播。这是解构:(但你很可能是对的,spread确实从对象中提取属性…)噢,我是说spread而不是destructure。很抱歉