diff --git a/packages/type/src/reflection/processor.ts b/packages/type/src/reflection/processor.ts index e563d1ecd..eb4ceb1d9 100644 --- a/packages/type/src/reflection/processor.ts +++ b/packages/type/src/reflection/processor.ts @@ -1450,6 +1450,8 @@ export class Processor { return { kind: ReflectionKind.never }; } + if (b.kind === ReflectionKind.unknown) return a; + 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 2e8f3528c..c36c27388 100644 --- a/packages/type/tests/type.spec.ts +++ b/packages/type/tests/type.spec.ts @@ -133,6 +133,31 @@ test('intersection with never', () => { expect(groupAnnotation.getAnnotations(typeOf())).toEqual(['c']); }); +test('intersection with unknown', () => { + // T & unknown = T (unknown is absorbed in intersections, per TypeScript semantics) + expect(stringifyType(typeOf())).toBe('string'); + expect(stringifyType(typeOf())).toBe('string'); + expect(stringifyType(typeOf())).toBe('number'); + expect(stringifyType(typeOf())).toBe('number'); + expect(stringifyType(typeOf())).toBe('boolean'); + expect(stringifyType(typeOf())).toBe('bigint'); + expect(stringifyType(typeOf())).toBe('null'); + expect(stringifyType(typeOf())).toBe('undefined'); + + // object literal & unknown = object literal + type MyObj = { a: string }; + expect(stringifyType(typeOf())).toBe('MyObj'); + expect(stringifyType(typeOf())).toBe('MyObj'); + + // class & unknown = class + class MyClass { name!: string; } + expect(stringifyType(typeOf())).toBe('MyClass'); + expect(stringifyType(typeOf())).toBe('MyClass'); + + // unknown & unknown = unknown + expect(stringifyType(typeOf())).toBe('unknown'); +}); + test('intersection same type keep annotation', () => { type MyAnnotation = { __meta?: never & ['myAnnotation'] }; type Username = string & MyAnnotation;