Skip to content

Commit

Permalink
feat(#43): add TestType
Browse files Browse the repository at this point in the history
  • Loading branch information
AshGw committed Apr 18, 2024
1 parent efbcb07 commit 935cef3
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 15 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
npm i ts-roids
```

### Example
### Examples
#### Lock a class (make it immutable) and finalize it (prohibit further extension)
```ts
import { locked, final } from 'ts-roids';
import type {
Expand All @@ -24,6 +25,12 @@ export class Foo<F> {
}
}
```
#### Quickly validates types using IntelliSense
```typescript
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 the types actually match, else false.

### Docs
Checkout the inline documentation in `/src` along with `/tests` to see how it works.
### License
Expand Down
95 changes: 81 additions & 14 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,51 @@ export type DeepMutate<T> = {
-readonly [K in Keys<T>]: DeepMutate<T[K]>;
};

type X = {
readonly a: () => 1;
readonly b: string;
readonly c: {
readonly d: boolean;
readonly e: {
readonly g: {
readonly h: {
readonly i: true;
readonly j: 's';
};
readonly k: 'hello';
};
};
};
};

type Expected = {
a: () => 1;
b: string;
c: {
d: boolean;
e: {
g: {
h: {
i: true;
j: 's';
};
k: 'hello';
};
};
};
};

export type DeepMutable<T extends Record<Keys<any>, any>> = T extends Callable<
OneOrMany<any>,
any
>
? T
: {
-readonly [K in Keys<T>]: DeepMutable<T[K]>;
};

export type ResultType = TestType<DeepMutable<X>, Expected, true>;

export type Immutate<T> = {
+readonly [K in Keys<T>]: T[K];
};
Expand Down Expand Up @@ -203,6 +248,42 @@ export type DeepNonNullableKeys<T> = {

export type Callable<A extends any[], R> = (...args: A) => R;

export type IfSame<T, P, Yes, No> = T extends P ? Yes : No;
export type ShallowEquals<X, Y> = X extends Y ? true : false;
export type Equals<X, Y> = (<T>() => T extends X ? true : false) extends <
T,
>() => T extends Y ? true : false
? true
: false;

export type MutableKeys<T> = keyof {
[P in Keys<T> as Equals<Pick<T, P>, Readonly<Pick<T, P>>> extends true
? never
: P]: never;
};

export type ImmutableKeys<T> = keyof {
[P in Keys<T> as Equals<Pick<T, P>, Readonly<Pick<T, P>>> extends true
? P
: never]: never;
};

declare function _testType<T1, T2, E extends boolean>(): Equals<
Equals<T1, T2>,
E
>;
export type TestType<T1, T2, Expected extends boolean> = ReturnType<
typeof _testType<T1, T2, Expected>
>;
// TODO: clean this shit
type Type1 = string;
type Type2 = string;
type Type3 = number;

export type Result1 = TestType<Type1, Type2, true>;
export type Result2 = TestType<Type1, Type3, false>;

/* class is fucking lockedin ong! */
export function locked(constructor: Newable): void {
function _sealAndFreeze(obj: object): void {
Object.seal(obj);
Expand All @@ -223,17 +304,3 @@ export function final<T extends Newable>(target: T): T {
}
};
}

export type IfSame<T, P, Yes, No> = T extends P ? Yes : No;
export type ShallowEquals<X, Y> = X extends Y ? true : false;
export type Equals<X, Y> = (<T>() => T extends X ? true : false) extends <
T,
>() => T extends Y ? true : false
? true
: false;

export type MutableKeys<T> = keyof {
[P in Keys<T> as Equals<Pick<T, P>, Readonly<Pick<T, P>>> extends true
? never
: P]: never;
};
23 changes: 23 additions & 0 deletions tests/test-type.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Keys, Primitive, Nullable, Numeric, TestType } from 'src';
import { test, expect } from 'vitest';

type Foo = {
bar: string;
foo: number;
fooBar: string;
};

test('_', () => {
type PersonKeys = Keys<Foo>;
const result: TestType<PersonKeys, 'bar' | 'foo' | 'fooBar', true> = true;
expect(result).toBe(true);
});

test('_', () => {
const result: TestType<
Primitive,
symbol | Nullable | string | Numeric | boolean,
true
> = true;
expect(result).toBe(true);
});

0 comments on commit 935cef3

Please sign in to comment.