Skip to content

Commit

Permalink
fix(lint): give single-letter generic params better names
Browse files Browse the repository at this point in the history
  • Loading branch information
ssube committed May 17, 2021
1 parent 8619bf1 commit 1b240fe
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 45 deletions.
36 changes: 21 additions & 15 deletions src/model/meta/Template.ts
Expand Up @@ -8,33 +8,39 @@ export interface TemplateNumber {
min: number;
}

export interface TemplateString<T extends string = string> {
/**
* A template string.
*
* Template string literal types are a strange idea, but needed to make string schemas typesafe, until constant string
* fields are removed from templates.
*/
export interface TemplateString<TBase extends string = string> {
type: 'string';
base: T;
base: TBase;
}

export interface TemplateRef {
type: 'id';
id: string;
}

export type TemplatePrimitive<T> =
T extends number ? TemplateNumber : // number -> range
T extends string ? TemplateString : // string -> template
T extends Metadata ? BaseTemplate<Omit<Metadata, 'template'>> : // Metadata + template -> Metadata
T extends Entity ? TemplateRef : // entity -> id
T extends Array<Entity> ? Array<TemplateRef> : // Array<entity> -> Array<id>
T extends Array<infer V> ? Array<TemplatePrimitive<V>> : // Array<V> -> Array<Template<V>>
T extends Map<infer K, infer V> ? Map<K, TemplatePrimitive<V>> : // Map<K, V> -> Map<K, Template<V>>
T extends object ? BaseTemplate<T> : // {[K]: V] -> {[K]: Template<V>}
export type TemplatePrimitive<TBase> =
TBase extends number ? TemplateNumber : // number -> range
TBase extends string ? TemplateString : // string -> template
TBase extends Metadata ? BaseTemplate<Omit<Metadata, 'template'>> : // Metadata + template -> Metadata
TBase extends Entity ? TemplateRef : // entity -> id
TBase extends Array<Entity> ? Array<TemplateRef> : // Array<entity> -> Array<id>
TBase extends Array<infer TValue> ? Array<TemplatePrimitive<TValue>> : // Array<TValue> -> Array<Template<TValue>>
TBase extends Map<infer TKey, infer TValue> ? Map<TKey, TemplatePrimitive<TValue>> : // Map<TKey, TValue> -> Map<TKey, Template<TValue>>
TBase extends object ? BaseTemplate<TBase> : // {[TKey]: TValue] -> {[TKey]: Template<TValue>}
never;

export type BaseTemplate<T> = {
[K in keyof T]: TemplatePrimitive<T[K]>;
export type BaseTemplate<TBase> = {
[TKey in keyof TBase]: TemplatePrimitive<TBase[TKey]>;
};

export interface Template<T> {
base: BaseTemplate<T>;
export interface Template<TBase> {
base: BaseTemplate<TBase>;
// mods: Array<Modifier>;
}

Expand Down
3 changes: 3 additions & 0 deletions src/service/input/ActorInputMapper.ts
Expand Up @@ -11,6 +11,9 @@ export interface ActorInputMapperOptions extends BaseOptions {
inputs: InputTypes;
}

/**
* @todo eliminate this construct entirely (this is a inappropriate service locator/provider)
*/
export class ActorInputMapper {
protected actors: Map<string, Input>;
protected container: Container;
Expand Down
5 changes: 5 additions & 0 deletions src/service/script/LocalScriptService.ts
Expand Up @@ -11,6 +11,11 @@ import { ItemStep } from './common/ItemStep';
import { ItemUse } from './common/ItemUse';
import { RoomStep } from './common/RoomStep';

/**
* Builtin scripts.
*
* @todo load scripts from one or more modules (DI and/or Node)
*/
const BASE_SCRIPTS: Array<[string, ScriptFunction]> = [
['actor-hit', ActorHit],
['actor-step', ActorStep],
Expand Down
25 changes: 17 additions & 8 deletions src/util/event/index.ts
@@ -1,30 +1,30 @@
import { doesExist } from '@apextoaster/js-utils';
import { EventEmitter } from 'events';

export interface RemoveResult<T> {
pending: Promise<T>;
export interface RemoveResult<TValue> {
pending: Promise<TValue>;
remove: () => void;
}

/**
* Wait for an event to fire once, then remove listeners. Provides a function to cleanup listeners early.
*/
export function onceWithRemove<TValue>(emitter: EventEmitter, event: string, inner?: () => void): RemoveResult<TValue> {
let error: (err: Error) => void;
let error: (err?: Error) => void;
let result: (value: TValue) => void;

const remove = () => {
emitter.removeListener('error', error);
emitter.removeListener(event, result);
};
// to resolve everything correctly, settled must be set before remove, and remove must be called before res/rej
let settled = false;

const pending = new Promise<TValue>((res, rej) => {
error = (err: Error) => {
error = (err?: Error) => {
settled = true;
remove();
rej(err);
};

result = (value: TValue) => {
settled = true;
remove();
res(value);
};
Expand All @@ -37,6 +37,15 @@ export function onceWithRemove<TValue>(emitter: EventEmitter, event: string, inn
}
});

const remove = () => {
emitter.removeListener('error', error);
emitter.removeListener(event, result);

if (settled === false) {
error(/* TODO: throw event aborted error */);
}
};

return {
pending,
remove,
Expand Down
24 changes: 12 additions & 12 deletions src/util/map.ts
@@ -1,32 +1,32 @@
import { doesExist, isNil } from '@apextoaster/js-utils';
import { doesExist } from '@apextoaster/js-utils';

import { BYTE_RANGE } from './constants';

export function decrementKey<T>(map: Map<T, number>, key: T, step = 1, min = 0): number {
export function decrementKey<TKey>(map: Map<TKey, number>, key: TKey, step = 1, min = 0): number {
const last = map.get(key);
if (isNil(last)) {
map.set(key, min);
return min;
} else {
if (doesExist(last)) {
const next = Math.max(min, last - step);
map.set(key, next);
return next;
} else {
map.set(key, min);
return min;
}
}

export function incrementKey<T>(map: Map<T, number>, key: T, step = 1, max = BYTE_RANGE, base = 0): number {
export function incrementKey<TKey>(map: Map<TKey, number>, key: TKey, step = 1, max = BYTE_RANGE, min = 0): number {
const last = map.get(key);
if (isNil(last)) {
map.set(key, base);
return base;
} else {
if (doesExist(last)) {
const next = Math.min(max, last + step);
map.set(key, next);
return next;
} else {
map.set(key, min);
return min;
}
}

export function getKey<T>(map: Map<T, number>, key: T, defaultValue = 0): number {
export function getKey<TKey>(map: Map<TKey, number>, key: TKey, defaultValue = 0): number {
const last = map.get(key);
if (doesExist(last)) {
return last;
Expand Down
2 changes: 1 addition & 1 deletion src/util/schema.ts
Expand Up @@ -5,7 +5,7 @@ import { TemplateString } from '../model/meta/Template';
/**
* @todo: make this typesafe for literal string types
*/
export function makeConstStringSchema<T extends string>(value: T): JSONSchemaType<TemplateString> {
export function makeConstStringSchema<TValue extends string>(value: TValue): JSONSchemaType<TemplateString> {
return {
type: 'object',
properties: {
Expand Down
2 changes: 1 addition & 1 deletion src/util/template/index.ts
Expand Up @@ -5,6 +5,6 @@ import { Template } from '../../model/meta/Template';

export type InputChain = Array<string | InputChain>;

export function findByTemplateId<T extends Entity>(templates: Array<Template<T>>, id: string): Template<T> {
export function findByTemplateId<TEntity extends Entity>(templates: Array<Template<TEntity>>, id: string): Template<TEntity> {
return mustFind(templates, (it) => it.base.meta.id.base === id);
}
16 changes: 8 additions & 8 deletions src/util/types.ts
Expand Up @@ -3,20 +3,20 @@
*
* From https://github.com/microsoft/TypeScript/issues/13923#issuecomment-653675557
*/
export type Immutable<T> =
export type Immutable<TBase> =
// eslint-disable-next-line @typescript-eslint/ban-types
T extends Function | boolean | number | string | null | undefined ? T :
T extends Array<infer U> ? ReadonlyArray<Immutable<U>> :
T extends Map<infer K, infer V> ? ReadonlyMap<Immutable<K>, Immutable<V>> :
T extends Set<infer S> ? ReadonlySet<Immutable<S>> :
{ readonly [P in keyof T]: Immutable<T[P]> };
TBase extends Function | boolean | number | string | null | undefined ? TBase :
TBase extends Array<infer TValue> ? ReadonlyArray<Immutable<TValue>> :
TBase extends Map<infer TKey, infer TValue> ? ReadonlyMap<Immutable<TKey>, Immutable<TValue>> :
TBase extends Set<infer TValue> ? ReadonlySet<Immutable<TValue>> :
{ readonly [TKey in keyof TBase]: Immutable<TBase[TKey]> };

export type KeyList<T> = Array<keyof T>;
export type KeyList<TList> = Array<keyof TList>;

/**
* Remove some fields and redefine them with another type.
*/
export type Replace<T, TKey extends keyof T, TValue> = Omit<T, TKey> & {
export type Replace<TBase, TKey extends keyof TBase, TValue> = Omit<TBase, TKey> & {
[K in TKey]: TValue;
};

Expand Down

0 comments on commit 1b240fe

Please sign in to comment.