تايب سكريبت: جزئي عميق؟
هل هناك طريقة لتحديد نوع جزئي في TypeScript تجعل أيضًا جميع الكائنات الفرعية جزئية؟ على سبيل المثال:
interface Foobar {
foo: number;
bar: {
baz: boolean;
qux: string;
};
}
const foobar: Partial<Foobar> = {
foo: 1,
bar: { baz: true }
};
هذا يطرح الخطأ التالي:
TS2741: Property 'qux' is missing in type '{ baz: true; }' but required in type '{ baz: boolean; qux: string; }'.
هل هناك أي طريقة لجعل العقد الفرعية جزئية أيضًا؟
الإجابة رقم 1
يمكنك ببساطة إنشاء نوع جديد، لنقل، DeepPartial، والذي يشير في الأساس إلى نفسه (تم التحديث في يناير 2022 للتعامل مع الكائنات المحتملة غير الموجودة):
type DeepPartial<T> = T extends object ? {
[P in keyof T]?: DeepPartial<T[P]>;
} : T;
ثم، يمكنك استخدامه على هذا النحو:
const foobar: DeepPartial<Foobar> = {
foo: 1,
bar: { baz: true }
};
انظر مثال الإثبات على المفهوم على TypeScript Playground.
الإجابة رقم 2
إذا كنت تبحث عن حل سريع وسهل، تحقق من حزمة type-fest، التي تحتوي على العديد من أنواع TypeScript الجاهزة المفيدة بما في ذلك النوع PartialDeep.
لحل أكثر تقنية وقابلية للتخصيص، انظر هذا الجواب.
الإجابة رقم 3
استلهمت نفسي من الإجابات على هذا السؤال لإنشاء نسختي الخاصة من PartialDeep.
لقد صادفت بعض المشاكل مع الكائنات المدمجة على طول الطريق؛ بالنسبة لحالتي الخاصة، لا أتوقع أن يفتقد كائن Date بعض طرقه. إما أن يكون موجودًا، أو لا يكون.
إليكم نسختي:
// Primitive types (+ Date) are themselves. Or maybe undefined.
type PartialDeep<T> = T extends string | number | bigint | boolean | null | undefined | symbol | Date
? T | undefined
// Arrays, Sets and Maps and their readonly counterparts have their items made
// deeply partial, but their own instances are left untouched
: T extends Array<infer ArrayType>
? Array<PartialDeep<ArrayType>>
: T extends ReadonlyArray<infer ArrayType>
? ReadonlyArray<ArrayType>
: T extends Set<infer SetType>
? Set<PartialDeep<SetType>>
: T extends ReadonlySet<infer SetType>
? ReadonlySet<SetType>
: T extends Map<infer KeyType, infer ValueType>
? Map<PartialDeep<KeyType>, PartialDeep<ValueType>>
: T extends ReadonlyMap<infer KeyType, infer ValueType>
? ReadonlyMap<PartialDeep<KeyType>, PartialDeep<ValueType>>
// ...and finally, all other objects.
: {
[K in keyof T]?: PartialDeep<T[K]>;
};
الإجابة رقم 4
قم ببساطة بإنشاء نوع جديد DeepPartial
DeepPartial يشير أساسًا إلى نفسه عندما تكون خاصيته من نوع object ليطبق DeepPartial على خصائص تلك الخاصية وهكذا
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K]
}
استخدام
interface Foobar {
foo: number;
bar: {
foo1: boolean;
bar1: string;
};
}
const foobar: DeepPartial<Foobar> = {
foo: 1,
bar: { foo1: true }
};
مثال ملعب TS
