From 69494ebd28bd733db4425cd6b4e0a5447be9da10 Mon Sep 17 00:00:00 2001 From: Matthieu Jolimaitre Date: Thu, 12 Dec 2024 18:18:47 +0100 Subject: [PATCH] add ClassMap data structure --- src/lib.ts | 1 + src/lib/ClassMap.ts | 65 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/lib/ClassMap.ts diff --git a/src/lib.ts b/src/lib.ts index d1903ff..7585cdc 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -25,3 +25,4 @@ export { Channel } from "./lib/Channel.ts"; export { Range, range } from "./lib/Range.ts"; export { Event } from "./lib/Event.ts"; export { AsyncPool } from "./lib/AsyncPool.ts"; +export { ClassMap } from "./lib/ClassMap.ts"; diff --git a/src/lib/ClassMap.ts b/src/lib/ClassMap.ts new file mode 100644 index 0000000..6a0c703 --- /dev/null +++ b/src/lib/ClassMap.ts @@ -0,0 +1,65 @@ +import { assert } from "https://deno.land/std@0.224.0/assert/assert.ts"; +import { assertInstanceOf } from "https://deno.land/std@0.224.0/assert/assert_instance_of.ts"; + +export type Prototyped

= { constructor: { prototype: P } }; +// deno-lint-ignore no-explicit-any +export type Constructible = new (...args: any[]) => I; +export class ClassMap { + private inner; + + constructor() { + this.inner = new Map(); + } + + insert(object: V) { + const prototype = object.constructor.prototype; + if (this.inner.has(prototype)) throw new Error(); + this.inner.set(prototype, object); + } + + get>(class_: C) { + const value = this.inner.get(class_.prototype); + if (value === undefined) return null; + assertInstanceOf(value, class_); + return value; + } + + has>(class_: C) { + return this.inner.has(class_.prototype); + } +} + +Deno.test("test_classmap", () => { + { + class Truc {} + class Machin {} + class Chose {} + + const map = new ClassMap(); + const truc = new Truc(); + map.insert(truc); + const machin = new Machin(); + map.insert(machin); + + assert(map.get(Truc) === truc); + assert(map.get(Machin) !== truc); + assert(map.get(Machin) === machin); + assert(map.get(Chose) === null); + } + { + interface Machinable { + machin(): number; + } + // deno-lint-ignore no-unused-vars + class Truc {} + class Machin implements Machinable { + machin = () => 35; + } + const map = new ClassMap(); + map.insert(new Machin()); + // map.insert(new Truc()); // note : Fails with improper typing. + + map.get(Machin); + // map.get(Truc); // note : Fails with improper typing. + } +});