Improve Typesafety on API Wrapper

This commit is contained in:
TheMas3212 2022-03-30 10:11:13 +11:00
parent 40f74e4a98
commit 8c58f0676d
2 changed files with 15 additions and 11 deletions

@ -6,15 +6,18 @@ import { makeRuntimeRejectMsg } from "../NetscriptEvaluator";
import { Player } from "../Player"; import { Player } from "../Player";
// type TargetFn<T> = (...args: [T, ...any[]]) => Promise<any>; type ExternalFunction = (...args: any[]) => any;
// type WrappedFn<F> = F extends (a: infer A1, ...args: infer U) => Promise<infer R> ? (a: A1|A1[], ...args: U) => Promise<R> : unknown; type ExternalAPI = {
// Need to think more about how to get these types to work [string: string]: ExternalAPI | ExternalFunction;
type InternalNetscriptFunction = (ctx: NetscriptContext, ...args: unknown[]) => unknown;
type WrappedNetscriptFunction = (...args: unknown[]) => unknown;
export type InternalNetscriptAPI = {
[string: string]: InternalNetscriptAPI | InternalNetscriptFunction;
} }
export type WrappedNetscriptAPI = {
type InternalFunction<F extends (...args: unknown[]) => unknown> = (ctx: NetscriptContext, ...args: unknown[]) => ReturnType<F>;
export type InternalAPI<API> = {
[Property in keyof API]: API[Property] extends ExternalFunction ? InternalFunction<API[Property]> : API[Property] extends ExternalAPI ? InternalAPI<API[Property]> : never;
}
type WrappedNetscriptFunction = (...args: unknown[]) => unknown;
type WrappedNetscriptAPI = {
[string: string]: WrappedNetscriptAPI | WrappedNetscriptFunction; [string: string]: WrappedNetscriptAPI | WrappedNetscriptFunction;
} }
@ -84,7 +87,7 @@ function wrapFunction<T>(helpers: NetscriptHelpers, wrappedAPI: any, workerScrip
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function wrapAPI(helpers: NetscriptHelpers, wrappedAPI: any, workerScript: WorkerScript, namespace: any, ...tree: string[]): WrappedNetscriptAPI { export function wrapAPI(helpers: NetscriptHelpers, wrappedAPI: ExternalAPI, workerScript: WorkerScript, namespace: any, ...tree: string[]): WrappedNetscriptAPI {
if (typeof namespace !== 'object') throw new Error('Invalid namespace?'); if (typeof namespace !== 'object') throw new Error('Invalid namespace?');
for (const property of Object.getOwnPropertyNames(namespace)) { for (const property of Object.getOwnPropertyNames(namespace)) {
switch (typeof namespace[property]) { switch (typeof namespace[property]) {

@ -9,11 +9,12 @@ import { Fragments, FragmentById } from "../CotMG/Fragment";
import { import {
Fragment as IFragment, Fragment as IFragment,
ActiveFragment as IActiveFragment, ActiveFragment as IActiveFragment,
Stanek as IStanek
} from "../ScriptEditor/NetscriptDefinitions"; } from "../ScriptEditor/NetscriptDefinitions";
import { AugmentationNames } from "../Augmentation/data/AugmentationNames"; import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
import { NetscriptContext, InternalNetscriptAPI } from "src/Netscript/APIWrapper"; import { NetscriptContext, InternalAPI } from "src/Netscript/APIWrapper";
export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): InternalNetscriptAPI { export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): InternalAPI<IStanek> {
function checkStanekAPIAccess(func: string): void { function checkStanekAPIAccess(func: string): void {
if (!player.hasAugmentation(AugmentationNames.StaneksGift1, true)) { if (!player.hasAugmentation(AugmentationNames.StaneksGift1, true)) {
helper.makeRuntimeErrorMsg(func, "Requires Stanek's Gift installed."); helper.makeRuntimeErrorMsg(func, "Requires Stanek's Gift installed.");