![](/img/trans.png)
[英]TypeScript: Can I check if a type contains undefined even when strictNullChecks is false?
[英]How to prevent `Required<T>` in typescript from removing 'undefined' from the type when using --strictNullChecks
打字稿讓您免去“optionability” (?)
與-?
映射類型修飾符,可以很容易地與Required<T>
類型一起使用。
type Required<T> = { [P in keyof T]-?: T[P] };
但是,在使用--strictNullChecks
時注意以下幾點很重要(就像我一樣)。
請注意,在 --strictNullChecks 模式下,當同態映射類型刪除 ? 基礎類型中屬性的修飾符,它還從該屬性的類型中刪除 undefined:
我正在尋找一種方法來繞過這種副作用......
即我想刪除?
但如果|undefined
存在我想保留它
為什么?
我有服務器生成的接口,這些接口具有可選 ( ?
) 屬性。 我想重構我的服務器代碼並添加/刪除成員。 因此,我想要一種方法,無論是否需要,我都必須為每個屬性顯式設置一個值(或顯式設置為undefined
)。
困境:
Required<T>
那么它會吞下我的| undefined
| undefined
但| undefined
是還有一個?
展示。因此,具有諷刺意味的是以下內容:
export type RequiredDog = Required <{
bark: 'loud' | 'quiet' | undefined,
bite?: 'nip' | 'clamp' | undefined
}>;
實際上變成了這樣:
type RequiredDog = {
bark: "loud" | "quiet" | undefined;
bite: "nip" | "clamp";
}
所以比bark
更可選的bite
現在實際上更少可選了!
有沒有辦法去掉?
不刪除undefined
?
如果我試圖實現一個不會從屬性中剝離undefined
的Required<>
,我可能會這樣做:
type RequiredKeepUndefined<T> = { [K in keyof T]-?: [T[K]] } extends infer U
? U extends Record<keyof U, [any]> ? { [K in keyof U]: U[K][0] } : never
: never;
我在這里用一堆映射和條件類型做的是將值類型包裝在一個單元組中,使其成為Required
,然后解開單元組。 這在精神上與您的答案相似,但如果有人在屬性中使用"undefined"
作為字符串文字,則不會發生沖突。
您可以看到它的行為符合要求:
interface Dog {
bark: "loud" | "quiet" | undefined;
bite?: "nip" | "clamp" | undefined;
}
type RequiredKeepUndefinedDog = RequiredKeepUndefined<Dog>
/* type RequiredKeepUndefinedDog = {
bark: "loud" | "quiet" | undefined;
bite: "nip" | "clamp" | undefined;
} */
您可以將其視為以下轉換
{bark: "loud" | "quiet" | undefined, bite?: "nip" | "clamp" | undefined}
{bark: ["loud" | "quiet" | undefined], bite?: ["nip" | "clamp" | undefined] | undefined}
{bark: ["loud" | "quiet" | undefined], bite: ["nip" | "clamp" | undefined]}
{bark: "loud" | "quiet" | undefined, bite: "nip" | "clamp" | undefined}
好的,希望有幫助; 祝你好運!
我仍然喜歡更清潔的解決方案,但以下似乎有效:
我基本上創建了一個名為'undefined'
的類型,我用這兩個替換/取消替換了真正的undefined
類型:
type WrapUndefined<T> = {
[P in keyof T]: undefined extends T[P] ? 'undefined' | T[P] : T[P];
};
type UnwrapUndefined<T> = {
[P in keyof T]: 'undefined' extends T[P] ? Diff<T[P], 'undefined'> | undefined : T[P];
};
所以如果我有:
type Person = {
firstName?: string;
}
然后WrapUndefined<Person>
使它
firstName?: string | undefined | 'undefined'; // *
然后,您可以對此調用Required<T>
以獲取此信息:
firstName: string | 'undefined'; // 'undefined' doesn't get removed now
然后用UnwrapUndefined<T>
反轉它得到
firstName: string | undefined;
所以我然后創建一個單一類型來完成所有這些:
export type SmartRequired<T> = UnwrapUndefined<Required<WrapUndefined<T>>>;
如果我在我原來的Dog
類型上運行這個問題,我會得到我想要的:
export type RequiredDog = SmartRequired <{
bark: 'loud' | 'quiet' | undefined,
bite?: 'nip' | 'clamp' | undefined
}>;
這是哪個
type RequiredDog = {
bark: "loud" | "quiet" | undefined;
bite: "nip" | "clamp" | undefined;
}
* 高級說明:此步驟在 VSCode 中顯示為string | undefined
string | undefined
因為它似乎正在將 'undefined' 吸收到string
。 幸運的是,當您運行所有三個步驟時,它最終會得到正確的結果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.