【发布时间】:2019-12-10 22:54:20
【问题描述】:
Typescript 允许您使用 -? 映射类型修饰符删除“可选项性”(?),以便与 Required<T> 类型一起使用。
type Required<T> = { [P in keyof T]-?: T[P] };
但是在使用--strictNullChecks 时注意following 很重要(就像我一样)。
注意,在 --strictNullChecks 模式下,当同态映射类型 删除一个?来自基础类型中的属性的修饰符 从该属性的类型中删除 undefined:
我正在寻找绕过这种副作用的方法...
即我想删除? 但如果|undefined 存在我想保留它
为什么?
我有服务器生成的接口,这些接口具有可选的 (?) 属性。我想重构我的服务器代码并添加/删除成员。因此,我想要一种方法,无论是否需要,我都必须为每个属性显式设置一个值(或显式设置为 undefined)。
困境:
- 如果我使用
Required<T>,那么它会吞噬我的| undefined,但前提是还存在?。
因此,以下内容颇具讽刺意味:
export type RequiredDog = Required <{
bark: 'loud' | 'quiet' | undefined,
bite?: 'nip' | 'clamp' | undefined
}>;
居然变成了这样:
type RequiredDog = {
bark: "loud" | "quiet" | undefined;
bite: "nip" | "clamp";
}
所以bite 比bark 更可选,现在实际上更少可选!
有没有办法在不删除undefined 的情况下删除??
【问题讨论】:
-
我重读了你的“为什么?”段落四次,我仍然不明白为什么重构您的服务器代码添加/删除成员会导致您希望必须显式编写具有值
undefined的属性的结论。这些属性是可选的。所以...? (有时,如果“如何”问题很清楚,“为什么”并不重要[就像这里一样]。但在这里我认为理解“为什么”可能会导致问题的最终答案,这可能并不完全“如何”要求... :-) ) -
@T.J.Crowder 归结为几件事。仅仅因为某些东西在一天结束时(在 API 中)是“可选的”,并不意味着您不必考虑价值的来源。假设我添加了
Address3- 当然这是可选的 - 但如果我实际使用它,我需要记住设置它。如果我把它重命名为AddressLine3。它变得更加棘手。我想要的只是确保我没有忘记任何东西。 API 可能会改变,我希望编译器尽可能多地告诉我。当我添加一些东西或重命名它并且没有额外的打字错误时,我会感到紧张!... -
在 .NET 和 typescript/JS 工作之间存在一些微妙之处,首先是必需的/可为空的/未定义的意思,这肯定会使事情复杂化。我正在使用 Swagger 代码生成,我可以使用
[JsonRequired]来防止生成?。那么问题是,虽然'null'与打字稿中的undefined不同,但.NET服务器并没有做出这种区分。因此,如果我发送 null 它会爆炸。所以它必须是可选的。 -
我遇到的实际问题(导致我写这个问题)是我有一些源自服务器的字段,通过
Pick<T>映射到另一种类型,然后最终发送回服务器.如果它们是可选的(因为 .NET 不匹配),那么很容易忘记将每个字段复制回来。在正确的位置插入我的答案中的SmartRequired<T>突然揭示了我所缺少的东西。 (我现在可以睡觉了!)