تايبسكريبت - هل من الممكن استبعاد كائن فارغ من اتحاد؟


لدي اتحاد من نوعين، أحدهما كائن فارغ.

type U = {} | { a: number } // | { b: string } | { c: boolean } ....

أود استثناء الكائن الفارغ من الاتحاد ومع ذلك Exclude لا يساعد

type A = Exclude<U, {}>
// A = never

حاولت استخدام as const لكن النتيجة هي نفسها

const empty = {} as const
type Empty = typeof empty
type U = Empty | { a: number }
type A = Exclude<U, Empty>
//type A = never

المفارقة الإضافية هي أن استبعاد الخصائص الأخرى أمر بسيط

  type B = Exclude<U, { a: number }>
  // type B = {}

ملعب TS

هل من الممكن استبعاد واجهة فارغة من واجهات أخرى في اتحاد؟

الإجابة رقم 1

أجيب عن سؤالي بنفسي..

إذا كنت تستخدم AtLeastOne من إجابة @lukasgeiter هنا: استبعاد الكائن الفارغ من نوع Partial

يمكنك أن تفعل ما يلي:

type AtLeastOne<T, U = {[K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U];
    
type ExcludeEmpty<T> = T extends AtLeastOne<T> ? T : never; 
    
type U = {} | { a: number } | { b: string }
    
type Foo = ExcludeEmpty<U> // { a: number } | { b: string }

ملعب تي إس

الإجابة رقم 2

من الوثائق الخاصة بالكتابة الشرطية هنا، يمكنك فعليًا تعيين الأنواع بناءً على بعض الشروط.

T extends U ? X : Y

لذلك بالنسبة للسؤال أعلاه، ما يمكنك فعله هو استخدام الكلمة المفتاحية keyof التي تُستخدم لاستخراج المفاتيح من الكائنات. عندما لا يتم العثور على أي مفاتيح، يكون النوع never، لذلك يمكننا التحقق مما إذا كان keyof object يمتد إلى never أم لا، أي.

 keyof K extends never

لذا دمج الطباعة الشرطية أدناه؛

const empty = {} as const
type Empty = typeof empty

type NoEmpty<K> = keyof K extends never ? never : K;

type C = NoEmpty<Empty>;

type U = NoEmpty<Empty> | NoEmpty<{ a: number }>

يمكنك أخيرًا رؤية أن نوع U يكون كائنًا غير فارغ أي استبعاد الكائن الفارغ. تحقق من هذا الملعب