【发布时间】:2022-12-18 04:50:30
【问题描述】:
我目前正在尝试创建一个实用程序类型来解包 sniptt monads 选项。到目前为止,这是我的代码:
export interface Option<T> {
type: symbol;
isSome(): boolean;
isNone(): boolean;
match<U>(fn: Match<T, U>): U;
map<U>(fn: (val: T) => U): Option<U>;
andThen<U>(fn: (val: T) => Option<U>): Option<U>;
or<U>(optb: Option<U>): Option<T | U>;
and<U>(optb: Option<U>): Option<U>;
unwrapOr(def: T): T;
unwrap(): T | never;
}
export type UnwrappedOptionsType<T> = T extends (infer U)[]
? UnwrappedOptionsType<U>[]
: T extends object
? {
[P in keyof T]: T[P] extends Option<infer R>
? UnwrappedOptionsType<R> | undefined
: UnwrappedOptionsType<T[P]>;
}
: T;
我期望发生的是类型被推断出来并且选项属性是可选的。假设我有以下类型:
type SignUpRequest = {
username: string;
password: string;
email: Option<string>;
}
当我使用 UnwrappedOptionsType<SignUpRequest> 时,我希望得到以下类型:
{
username: string;
password: string;
email?: string | undefined;
}
我得到的是:
{
username: string;
password: string;
email: string;
}
它能够成功地推断出选项的类型,但它从来没有做到这一点,所以它也接受undefined。如何使选项可选?
编辑:更改代码以使示例可重现。此外,我特别希望属性是可选的,而不仅仅是可能未定义。
【问题讨论】:
-
什么是“sniptt monads 选项”?您能否edit 代码使其成为不依赖于任何第三方代码的独立minimal reproducible example?这样我们就可以将它粘贴到一个独立的 IDE 中,查看问题,并希望修复它。另请注意,在
{x: string | undefined}中,x不是可选的,它是必需的,但允许为undefined。你关心可选的(比如{x?: string})吗?或者是 required-but-could-be-undefined对你来说足够好了吗? -
@jcalz 我更新了问题。
-
大概您关心嵌套属性;你能更新你的例子来展示你想在那里发生什么吗?另外,工会呢?
{x: string | Option<number>}应该变成{x: string | number | undefined}或{x?: string | number}或{x: string} | {x?: number}还是其他什么? -
我的意思是,this approach 是我在这里的倾向,但我不知道它是否像您希望的那样处理边缘情况。我们应该如何着手?
-
@jcalz 这对我来说非常有用。如果您发布它,我会接受它作为答案。
标签: typescript