Skip to content

Commit

Permalink
fix(type): intersection of two different primitive types always retur…
Browse files Browse the repository at this point in the history
…n never (#549)

Signed-off-by: Marc J. Schmidt <[email protected]>
Co-authored-by: Marc J. Schmidt <[email protected]>
  • Loading branch information
M-jerez and marcj authored Feb 10, 2024
1 parent 732feec commit 20d3dc8
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 0 deletions.
5 changes: 5 additions & 0 deletions packages/type/src/reflection/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
16 changes: 16 additions & 0 deletions packages/type/tests/type.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@ test('intersection same type', () => {
expect(stringifyType(typeOf<Username & string>())).toBe('Username');
});


test('intersection different primitive types', () => {
// just testing a few cases as there would be quite a few combinations
expect(stringifyType(typeOf<string & number>())).toBe('never');
expect(stringifyType(typeOf<undefined & null>())).toBe('never');
expect(stringifyType(typeOf<boolean & null>())).toBe('never');
expect(stringifyType(typeOf<bigint & number>())).toBe('never');
expect(stringifyType(typeOf<3 & 6>())).toBe('never');
});

test('intersection with never', () => {
type A = never & Group<'a'>;
type B = Group<'b'> & never;
Expand Down Expand Up @@ -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<t1>() as TypeObjectLiteral;
const password1 = findMember('password', type1.types) as TypeProperty;
expect(password1.optional).toBe(true);
expect(password1.readonly).toBe(true);
});

test('copy index access', () => {
Expand Down

0 comments on commit 20d3dc8

Please sign in to comment.