From 20d3dc83a00431db99f6feb0f41da890fa422f48 Mon Sep 17 00:00:00 2001 From: Ma Jerez Date: Sat, 10 Feb 2024 13:46:26 +0000 Subject: [PATCH] fix(type): intersection of two different primitive types always return never (#549) Signed-off-by: Marc J. Schmidt Co-authored-by: Marc J. Schmidt --- packages/type/src/reflection/processor.ts | 5 +++++ packages/type/tests/type.spec.ts | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/packages/type/src/reflection/processor.ts b/packages/type/src/reflection/processor.ts index 9cff5f6f2..908610450 100644 --- a/packages/type/src/reflection/processor.ts +++ b/packages/type/src/reflection/processor.ts @@ -1400,6 +1400,11 @@ export class Processor { return isExtendable(a, b) ? a : { kind: ReflectionKind.never }; } + // two different primitives always return never + if (isPrimitive(a) && isPrimitive(b) && a.kind !== b.kind) { + return { kind: ReflectionKind.never } + } + if (a.kind === ReflectionKind.objectLiteral || a.kind === ReflectionKind.class || a.kind === ReflectionKind.never || a.kind === ReflectionKind.unknown) return b; if (b.annotations) { diff --git a/packages/type/tests/type.spec.ts b/packages/type/tests/type.spec.ts index 1198c9990..f9412a468 100644 --- a/packages/type/tests/type.spec.ts +++ b/packages/type/tests/type.spec.ts @@ -97,6 +97,16 @@ test('intersection same type', () => { expect(stringifyType(typeOf())).toBe('Username'); }); + +test('intersection different primitive types', () => { + // just testing a few cases as there would be quite a few combinations + expect(stringifyType(typeOf())).toBe('never'); + expect(stringifyType(typeOf())).toBe('never'); + expect(stringifyType(typeOf())).toBe('never'); + expect(stringifyType(typeOf())).toBe('never'); + expect(stringifyType(typeOf<3 & 6>())).toBe('never'); +}); + test('intersection with never', () => { type A = never & Group<'a'>; type B = Group<'b'> & never; @@ -146,6 +156,12 @@ test('intersection simply overrides properties', () => { const password = findMember('password', type.types); assertType(password, ReflectionKind.propertySignature); assertType(password.type, ReflectionKind.void); + + type t1 = User & { readonly password?: string }; + const type1 = typeOf() as TypeObjectLiteral; + const password1 = findMember('password', type1.types) as TypeProperty; + expect(password1.optional).toBe(true); + expect(password1.readonly).toBe(true); }); test('copy index access', () => {