Skip to content

Commit

Permalink
feat(#54): finish DeepOmit<T,SL>
Browse files Browse the repository at this point in the history
  • Loading branch information
ashgw committed Apr 19, 2024
1 parent e384ba9 commit 65ab454
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 27 deletions.
76 changes: 76 additions & 0 deletions CHANGELOG.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ts-roids",
"version": "1.18.0",
"version": "1.20.1",
"private": false,
"description": "Extending the TS library with types and decorators that should've been built-in",
"keywords": [
Expand Down
57 changes: 31 additions & 26 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,27 +275,31 @@ export type NewType<N> = {
[__s]: true;
} & N;

export type obj = {
person: {
name: string;
age: {
value: number;
};
};
};

export type DeepOmit<T, Str extends string> = Str extends `${string}.${infer R}`
/**
* Type that recursively omits specified nested properties from an object type.
* @template T The input object type.
* @template P A string literal representing the path of properties to omit (e.g., 'person.name.value').
* @example
* ```typescript
* type T =
* a: {
* b: string;
* b2: {
* c: {
* d: number;
* };
* };
* };
* }
*
* DeepOmit<T, 'a.b2.c'> // Results in: { a: { b: string; b2: {} } }
* ```
*/
export type DeepOmit<T, P extends string> = P extends `${infer K}.${infer R}`
? {
[K in Keys<T>]: DeepOmit<T[K], R>;
[KT in Keys<T>]: KT extends K ? DeepOmit<T[KT], R> : T[KT];
}
: T extends unknown
? Omit<T, Str>
: T;

export type test1 = DeepOmit<obj, 'person'>; // {}
export type test2 = DeepOmit<obj, 'person.name'>; // { person: { age: { value: number } } }
export type test3 = DeepOmit<obj, 'name'>; // { person: { name: string; age: { value: number } } }
export type test4 = DeepOmit<obj, 'person.age.value'>; // { person: { name: string; age: {} } }
: Omit<T, P>;

export type EmptyArray = [];
/**
Expand Down Expand Up @@ -327,9 +331,9 @@ export type ArrayTranspose<
};
};

export type Matrix = ArrayTranspose<[[1]]>; //[[1]]
export type Matrix1 = ArrayTranspose<[[1, 'i'], [3, 4]]>; // [[1, 3], ["i", 4]]
export type Matrix2 = ArrayTranspose<[[1, true, 3], [4, 5, 6]]>; // [[1, 4], [true, 5], [3, 6]]
export type Matrix2 = ArrayTranspose<
[[1, Optional<number>, Nullable, 3], [4, 5, 6]]
>; // [[1, 4], [true, 5], [3, 6]]

export type AlterKeyTypeWith<T, K extends Keys<T>, R> = Pick<
T,
Expand Down Expand Up @@ -359,9 +363,9 @@ export type OmitBy<T, P> = Omit<T, FilterBy<T, P>>;

/**
* Represents a export type that filters elements from an array based on a given predicate export type.
* @typeParam T The array export type to filter.
* @typeParam P The predicate export type used for filtering elements from `T`.
* @returns a new array export type containing only the elements of `T` that match `P`.
* @typeParam T The array to filter.
* @typeParam P The predicate used for filtering elements from `T`.
* @returns a new array type containing only the elements of `T` that match `P`.
* @example
* ```typescript
* export type Numbers = [0, 1, 2, 3];
Expand All @@ -377,7 +381,8 @@ export type ArrayFilter<T extends unknown[], P> = T extends [
: ArrayFilter<E, P>
: [];

export type EmptyObject = Exclude<object, Nullable>;
export type EmptyObject = NonNullable<unknown>;
export type EmptyObject3 = Exclude<object, Nullable>;
export type EmptyObject2 = Record<string, never>;
export type OptionalKeys<T> = {
[K in Keys<T>]-?: EmptyObject extends Pick<T, K> ? K : never;
Expand Down
34 changes: 34 additions & 0 deletions tests/array-transpose.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Optional, Nullable, Numeric, TestType, ArrayTranspose } from 'src';
import { test, expect } from 'vitest';

test('_', () => {
const result: TestType<
ArrayTranspose<[[1, Optional<Numeric>, Nullable, 3], [4, 5, 6]]>,
[[1, 4], [Optional<Numeric>, 5], [Nullable, 6], [3, never]],
true
> = true;
expect(result).toBe(true);
});

test('_', () => {
const result: TestType<ArrayTranspose<[[1]]>, [[1]], true> = true;
expect(result).toBe(true);
});

test('_', () => {
const result: TestType<
ArrayTranspose<[[1, true, 3], [4, 5, 6]]>,
[[1, 4], [true, 5], [3, 6]],
true
> = true;
expect(result).toBe(true);
});

test('_', () => {
const result: TestType<
ArrayTranspose<[[1, 'i'], [3, 4]]>,
[[1, 3], ['i', 4]],
true
> = true;
expect(result).toBe(true);
});
41 changes: 41 additions & 0 deletions tests/deep-omit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { DeepOmit, TestType, EmptyObject } from 'src';
import { test, expect } from 'vitest';

type Actual = {
a: {
b: string;
b2: {
c: {
d: number;
};
};
};
};

test('_', () => {
const result: TestType<
DeepOmit<Actual, 'a.b2.c'>,
{ a: { b: string; b2: EmptyObject } },
true
> = true;
expect(result).toBe(true);
});

test('_', () => {
const result: TestType<
DeepOmit<Actual, 'a.b2.c'>,
{ a: { b: string; b2: EmptyObject } },
true
> = true;
expect(result).toBe(true);
});

test('_', () => {
const result: TestType<DeepOmit<Actual, 'a'>, EmptyObject, true> = true;
expect(result).toBe(true);
});

test('_', () => {
const result: TestType<DeepOmit<Actual, 'b'>, Actual, true> = true;
expect(result).toBe(true);
});

0 comments on commit 65ab454

Please sign in to comment.