Created
September 20, 2022 16:31
-
-
Save trueharuu/5e2322549ac5725e61af79c5c12581dc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Constructor<U extends Array<unknown>> = new (...args: U) => unknown; | |
type Keys<T, M = any> = keyof { | |
[P in keyof T as T[P] extends M ? P : never]: T[P]; | |
}; | |
export class Ops<T = {}> { | |
public mem: T = {} as never; | |
public define<K extends string, U>( | |
key: K, | |
value: U | |
): Ops<{ | |
[P in keyof T | K]: [P] extends [K] ? U : P extends keyof T ? T[P] : never; | |
}> { | |
this.mem[key as never] = value as never; | |
return this as never; | |
} | |
public remove<K extends keyof T>( | |
key: K | |
): Ops<{ | |
[P in keyof T as [P] extends [K] ? never : P]: T[P]; | |
}> { | |
delete this.mem[key]; | |
return this as never; | |
} | |
public access<U extends Keys<T>>(name: U): T[U] { | |
return this.mem[name]; | |
} | |
public set<U extends Keys<T>>(name: U, value: T[U]) { | |
this.mem[name] = value; | |
return this; | |
} | |
public property<U extends Keys<T, object>>(name: U, property: keyof T[U]) { | |
return Reflect.get(this.access(name as never) as object, property); | |
} | |
public call<U extends Keys<T, Function>>( | |
name: U, | |
args: Parameters<T[U] extends (...args: any[]) => any ? T[U] : never> | |
): ReturnType<T[U] extends (...args: any[]) => any ? T[U] : never> { | |
return (this.access(name as never) as Function)(args); | |
} | |
public construct<K extends Keys<T, Constructor<U>>, U extends Array<unknown>>( | |
name: K, | |
args: U | |
): unknown { | |
return Reflect.construct( | |
this.access(name as never) as Constructor<U>, | |
args | |
); | |
} | |
public delete<U extends Keys<T>>( | |
name: U, | |
key: keyof { | |
[P in keyof T[U] as undefined extends T[U][P] ? P : never]: T[U][P]; | |
} | |
) { | |
delete this.mem[name][key]; | |
return this; | |
} | |
public void<U extends Keys<T>>(name: U): void { | |
return void this.mem[name]; | |
} | |
public num(name: Keys<T>): number { | |
return Number(this.access(name)); | |
} | |
public neg(name: Keys<T>): number { | |
return this.num(name) * -1; | |
} | |
public bitwiseNot(name: Keys<T, number>): number { | |
return ~this.access(name as never); | |
} | |
public bitwiseAnd(source: Keys<T, number>, target: Keys<T, number>): number { | |
return ( | |
(this.access(source as never) as number) & | |
(this.access(target as never) as number) | |
); | |
} | |
public bitwiseOr(source: Keys<T, number>, target: Keys<T, number>): number { | |
return ( | |
(this.access(source as never) as number) | | |
(this.access(target as never) as number) | |
); | |
} | |
public bitwiseXor(source: Keys<T, number>, target: Keys<T, number>): number { | |
return ( | |
(this.access(source as never) as number) ^ | |
(this.access(target as never) as number) | |
); | |
} | |
public bitwiseShiftLeft( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): number { | |
return ( | |
(this.access(source as never) as number) << | |
(this.access(target as never) as number) | |
); | |
} | |
public bitwiseShiftRight( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): number { | |
return ( | |
(this.access(source as never) as number) >> | |
(this.access(target as never) as number) | |
); | |
} | |
public bitwiseShiftRightUnsigned( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): number { | |
return ( | |
(this.access(source as never) as number) >>> | |
(this.access(target as never) as number) | |
); | |
} | |
public assignBitwiseAnd( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): this { | |
return this.set(source as never, this.bitwiseAnd(source, target) as never); | |
} | |
public assignBitwiseOr( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): this { | |
return this.set(source as never, this.bitwiseOr(source, target) as never); | |
} | |
public assignBitwiseXor( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): this { | |
return this.set(source as never, this.bitwiseXor(source, target) as never); | |
} | |
public assignBitwiseShiftLeft( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): this { | |
return this.set( | |
source as never, | |
this.bitwiseShiftLeft(source, target) as never | |
); | |
} | |
public assignBitwiseShiftRight( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): this { | |
return this.set( | |
source as never, | |
this.bitwiseShiftRight(source, target) as never | |
); | |
} | |
public assignBitwiseShiftRightUnsigned( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): this { | |
return this.set( | |
source as never, | |
this.bitwiseShiftRightUnsigned(source, target) as never | |
); | |
} | |
public ternary<T, U>(condition: Keys<T, boolean>, then: T, el: U): T | U { | |
return this.access(condition as never) ? then : el; | |
} | |
public logicalAnd( | |
source: Keys<T, boolean>, | |
target: Keys<T, boolean> | |
): boolean { | |
return ( | |
(this.access(source as never) as boolean) && | |
(this.access(target as never) as boolean) | |
); | |
} | |
public logicalOr( | |
source: Keys<T, boolean>, | |
target: Keys<T, boolean> | |
): boolean { | |
return ( | |
(this.access(source as never) as boolean) && | |
(this.access(target as never) as boolean) | |
); | |
} | |
public nullishCoalesce<U>(source: Keys<T, U>, target: Keys<T, U>): U { | |
return ( | |
(this.access(source as never) as U) ?? (this.access(target as never) as U) | |
); | |
} | |
public assignLogicalAnd( | |
source: Keys<T, boolean>, | |
target: Keys<T, boolean> | |
): this { | |
return this.set(source as never, this.logicalAnd(source, target) as never); | |
} | |
public assignLogicalOr( | |
source: Keys<T, boolean>, | |
target: Keys<T, boolean> | |
): this { | |
return this.set(source as never, this.logicalOr(source, target) as never); | |
} | |
public assignNullishCoalesce<U>( | |
source: Keys<T, U>, | |
target: Keys<T, U> | |
): this { | |
return this.set( | |
source as never, | |
this.nullishCoalesce(source, target) as never | |
); | |
} | |
public comma<U>(sources: [...Array<unknown>, U]): U { | |
return sources.at(-1) as U; | |
} | |
public add(source: Keys<T, number>, target: Keys<T, number>): number { | |
return ( | |
(this.access(source as never) as number) + | |
(this.access(target as never) as number) | |
); | |
} | |
public subtract(source: Keys<T, number>, target: Keys<T, number>): number { | |
return ( | |
(this.access(source as never) as number) - | |
(this.access(target as never) as number) | |
); | |
} | |
public multiply(source: Keys<T, number>, target: Keys<T, number>): number { | |
return ( | |
(this.access(source as never) as number) * | |
(this.access(target as never) as number) | |
); | |
} | |
public divide(source: Keys<T, number>, target: Keys<T, number>): number { | |
return ( | |
(this.access(source as never) as number) / | |
(this.access(target as never) as number) | |
); | |
} | |
public modulo(source: Keys<T, number>, target: Keys<T, number>): number { | |
return ( | |
(this.access(source as never) as number) % | |
(this.access(target as never) as number) | |
); | |
} | |
public exponentiate( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): number { | |
return ( | |
(this.access(source as never) as number) ** | |
(this.access(target as never) as number) | |
); | |
} | |
public assignAdd(source: Keys<T, number>, target: Keys<T, number>): this { | |
return this.set(source as never, this.add(source, target) as never); | |
} | |
public assignSubtract( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): this { | |
return this.set(source as never, this.subtract(source, target) as never); | |
} | |
public assignMultiply( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): this { | |
return this.set(source as never, this.multiply(source, target) as never); | |
} | |
public assignDivide(source: Keys<T, number>, target: Keys<T, number>): this { | |
return this.set(source as never, this.divide(source, target) as never); | |
} | |
public assignModulo(source: Keys<T, number>, target: Keys<T, number>): this { | |
return this.set(source as never, this.modulo(source, target) as never); | |
} | |
public assignExponentiate( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): this { | |
return this.set( | |
source as never, | |
this.exponentiate(source, target) as never | |
); | |
} | |
public increment(source: Keys<T, number>) { | |
this.set( | |
source as never, | |
((this.access(source as never) as number) + 1) as never | |
); | |
return this; | |
} | |
public decrement(source: Keys<T, number>) { | |
this.set( | |
source as never, | |
((this.access(source as never) as number) - 1) as never | |
); | |
return this; | |
} | |
public greaterThan( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): boolean { | |
return this.access(source as never) > this.access(target as never); | |
} | |
public lessThan(source: Keys<T, number>, target: Keys<T, number>): boolean { | |
return this.access(source as never) < this.access(target as never); | |
} | |
public greaterThanOrEqual( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): boolean { | |
return this.access(source as never) >= this.access(target as never); | |
} | |
public lessThanOrEqual( | |
source: Keys<T, number>, | |
target: Keys<T, number> | |
): boolean { | |
return this.access(source as never) <= this.access(target as never); | |
} | |
public equal<U>(source: Keys<T, U>, target: Keys<T, U>): boolean { | |
return this.access(source as never) == this.access(target as never); | |
} | |
public inequal<U>(source: Keys<T, U>, target: Keys<T, U>): boolean { | |
return this.access(source as never) != this.access(target as never); | |
} | |
public strictEqual<U>(source: Keys<T, U>, target: Keys<T, U>): boolean { | |
return this.access(source as never) === this.access(target as never); | |
} | |
public strictInequal<U>(source: Keys<T, U>, target: Keys<T, U>): boolean { | |
return this.access(source as never) !== this.access(target as never); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment