Skip to content

Commit

Permalink
feat(#50): finish UniqueArray<T>
Browse files Browse the repository at this point in the history
  • Loading branch information
ashgw committed Apr 18, 2024
1 parent b20b660 commit d713ccc
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type ResultType = TestType<Type1, Type2, true>;
```
``TestType`` accepts three arguments: the types you're comparing (``Type1`` and ``Type2``) and a boolean (true if you think they match, false otherwise). The resulting ``ResultType`` will tell if the choice is correct, true if it is, else false.
#### Create your own type
Instead of this loosely typed function
Check this loosely typed function
```typescript
function fooBar(foo: string, bar: string) {
if (condition(foo, bar)) {
Expand Down
22 changes: 21 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,15 +185,24 @@ type Expected = {
};
};

/**
* A type that recursively mutates all the proprties within a given object type `T`.
*/
export type DeepMutable<T> = T extends UnknownFunction
? T
: {
-readonly [K in Keys<T>]: T[K] extends unknown ? DeepMutable<T[K]> : T[K];
};

/**
* Checks if all the nested properties of a given object T is actually mutable.
*/
export type IsDeepMutable<T> = T extends DeepMutable<T> ? true : false;
export type ResultType = TestType<DeepMutable<X>, Expected, true>;

/**
* A type that recursively turns the proprties within a given object type `T` immutable.
*/
export type DeepImmutable<T> = T extends UnknownFunction
? T
: {
Expand All @@ -202,6 +211,9 @@ export type DeepImmutable<T> = T extends UnknownFunction
: T[K];
};

/**
* Checks if all the nested properties of a given object T is actually immutable.
*/
export type IsDeepImmutable<T> = T extends DeepImmutable<T> ? true : false;
export type ResultType1 = TestType<IsDeepImmutable<X>, true, true>;
export type ResultType2 = TestType<DeepImmutable<Expected>, X, true>;
Expand Down Expand Up @@ -243,7 +255,7 @@ declare const __s: unique symbol;
*/
export type NewType<N> = {
/**
* Property `__s` is not intended for direct access or modification.
* Property `__s` is not intended for direct access nor modification.
* @internal
*/
[__s]: true;
Expand Down Expand Up @@ -330,6 +342,14 @@ declare function _testType<T1, T2, E extends boolean>(): Equals<
Equals<T1, T2>,
E
>;
/**
* Represents a type validation utility to determine if two types match.
* @template T1 The first type to compare.
* @template T2 The second type to compare.
* @template Expected A boolean literal indicating whether `T1` should match `T2`.
* If you expect the types to match, set this to true; if not, set it to false.
* This utility will return a boolean that is true if your expectation was correct, otherwise false.
*/
export type TestType<T1, T2, Expected extends boolean> = ReturnType<
typeof _testType<T1, T2, Expected>
>;
Expand Down
54 changes: 54 additions & 0 deletions tests/deep-immutable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {
Falsy,
DeepImmutable,
IsDeepImmutable,
Primitive,
Maybe,
Nullable,
TestType,
} from 'src';
import { test, expect } from 'vitest';

type Actual = {
a: () => 1;
x: string;
s: {
q: Nullable;
s: {
i: {
x: {
o: Maybe<Primitive>;
n: Falsy;
};
e: 'foo';
};
};
};
};

type Expected = {
readonly a: () => 1;
readonly x: string;
readonly s: {
readonly q: Nullable;
readonly s: {
readonly i: {
readonly x: {
readonly o: Maybe<Primitive>;
readonly n: Falsy;
};
readonly e: 'foo';
};
};
};
};

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

test('_', () => {
const result: TestType<IsDeepImmutable<Expected>, true, true> = true;
expect(result).toBe(true);
});
52 changes: 52 additions & 0 deletions tests/deep-mutable.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
Falsy,
DeepMutable,
Primitive,
IsDeepMutable,
Maybe,
Nullable,
TestType,
} from 'src';
import { test, expect } from 'vitest';

type Actual = {
readonly a: () => 1;
readonly x: string;
readonly s: {
readonly q: Nullable;
readonly s: {
readonly i: {
readonly x: {
readonly o: Maybe<Primitive>;
readonly n: Falsy;
};
readonly e: 'foo';
};
};
};
};
type Expected = {
a: () => 1;
x: string;
s: {
q: Nullable;
s: {
i: {
x: {
o: Maybe<Primitive>;
n: Falsy;
};
e: 'foo';
};
};
};
};
test('_', () => {
const result: TestType<DeepMutable<Actual>, Expected, true> = true;
expect(result).toBe(true);
});

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

0 comments on commit d713ccc

Please sign in to comment.