Skip to content

Commit

Permalink
feat: add OmitExactlyByTypeDeep
Browse files Browse the repository at this point in the history
  • Loading branch information
ashgw committed Aug 11, 2024
1 parent ab7e014 commit 5080ab2
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 71 deletions.
58 changes: 34 additions & 24 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -988,7 +988,7 @@ export type ArrayFilter<T extends unknown[], P> = T extends [
>; // => [unknown, 'foo', any, never, '33', 33]
* ```
*/
export type ArrayUnique<T, R extends any[] = []> = T extends [
export type ArrayUnique<T, R extends unknown[] = []> = T extends [
infer S,
...infer E,
]
Expand Down Expand Up @@ -1817,33 +1817,43 @@ export type OmitByType<T, P> = {
* Get a set of properties from `T` whose type exactly matches `P`.
* @example
* ````ts
type OneLevelDeep = {
foo: boolean;
bar?: Numeric;
baz: Nullable;
fooBaz: bigint;
bazFoo: string | boolean;
};
type A = OmitExactlyByType<OneLevelDeep, bigint>
type deep = {
isActive: boolean;
count?: number;
description: string | null;
details: {
id: bigint;
name: string;
nested: {
title: string;
subtitle: string;
moreDetails: {
numberId: bigint;
};
};
};
additionalInfo: string | boolean;
}
type A = OmitExactlyByTypeDeep<deep, bigint>
// A results in:
{
foo: boolean;
bar?: Numeric;
baz: Nullable;
bazFoo: string | boolean;
{
isActive: boolean;
count?: number;
description: string | null;
details: {
name: string;
nested: {
title: string;
subtitle: string;
moreDetails: EmptyObject;
};
};
additionalInfo: string | boolean;
}
type B = OmitExactlyByType<OneLevelDeep, string | boolean>
// B results in
{
foo: boolean;
bar?: Numeric;
baz: Nullable;
fooBaz: bigint;
}
* ````
*/
export type OmitExactlyByType<T, P> = {
[K in Keys<T> as If<Equals<T[K], P>, never, K>]: T[K];
export type OmitExactlyByTypeDeep<T, P> = {
[K in Keys<T> as IfEquals<T[K], P, never, K>]: OmitExactlyByTypeDeep<T[K], P>;
};

/**
Expand Down
93 changes: 93 additions & 0 deletions tests/omit-exactly-by-type-deep.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import {
Numeric,
Nullable,
OmitExactlyByTypeDeep,
TestType,
EmptyObject,
} from 'src';
import { test, expect } from 'vitest';

type OneLevelDeep = {
foo: boolean;
bar?: Numeric;
baz: Nullable;
fooBaz: bigint;
bazFoo: string | boolean;
};

test('_', () => {
const result: TestType<
OmitExactlyByTypeDeep<OneLevelDeep, bigint>,
{
foo: boolean;
bar?: Numeric;
baz: Nullable;
bazFoo: string | boolean;
},
true
> = true;
expect(result).toBe(true);
});
test('_', () => {
const result: TestType<
OmitExactlyByTypeDeep<
{
isActive: boolean;
count?: number;
description: string | null;
details: {
id: bigint;
name: string;
nested: {
title: string;
subtitle: string;
moreDetails: {
numberId: bigint;
};
};
};
additionalInfo: string | boolean;
},
bigint
>,
{
isActive: boolean;
count?: number;
description: string | null;
details: {
name: string;
nested: {
title: string;
subtitle: string;
moreDetails: EmptyObject;
};
};
additionalInfo: string | boolean;
},
true
> = true;
expect(result).toBe(true);
});

test('matches the exact type, if it was OmitByType it would have pulled `foo` out', () => {
const result: TestType<
OmitExactlyByTypeDeep<OneLevelDeep, string | boolean>,
{
foo: boolean;
bar?: Numeric;
baz: Nullable;
fooBaz: bigint;
},
true
> = true;
expect(result).toBe(true);
});

test('_', () => {
const result: TestType<
OmitExactlyByTypeDeep<OneLevelDeep, true>,
OneLevelDeep,
true
> = true;
expect(result).toBe(true);
});
47 changes: 0 additions & 47 deletions tests/omit-exactly-by-type.test.ts

This file was deleted.

0 comments on commit 5080ab2

Please sign in to comment.