deepkit / deepkit-framework

A new full-featured and high-performance TypeScript framework
https://deepkit.io/
MIT License
3.14k stars 116 forks source link

[Feature] @deepkit/type Would be a "equals()" and "hash()" method generation in scope of the project? #282

Open freddi301 opened 2 years ago

freddi301 commented 2 years ago

It would be useful for hash maps (structural keys) and efficient comparisons (due to shadow classes)

Code example:

import { equals, hash } from "@deepkit/type";

type User = {
  id: number;
  name: string;
};

type Organization = {
  boss: User;
};

// use cases

equals<User>({ id: 1, name: "bob" }, { id: 2, name: "alice" }); // false

hash<User>({ id: 3, name: "john" }); // 45

hash<User>(
  { id: 3, name: "john" },
  {
    create: () => require("crypto").createHash("sha256"),
    update: (state, data) => state.update(data),
    digest: (state) => state.digest("hex"),
  }
);

// example of generated code

function equalsUser(a: User, b: User): boolean {
  return a.id === b.id && a.name === b.name;
}

type HashFunction<State, Output> = {
  create(): State;
  update(state: State, data: unknown): void;
  digest(state: State): Output;
};

function hashUser<State, Output>(
  user: User,
  hashFunction: HashFunction<State, Output> = defaultHashFunction,
  [state, isRoot] = [hashFunction.create(), true]
) {
  hashFunction.update(state, user.id);
  hashFunction.update(state, user.name);
  if (isRoot) return hashFunction.digest(state);
}

function hashOrganization<State, Output>(
  organization: Organization,
  hashFunction: HashFunction<State, Output> = defaultHashFunction,
  [state, isRoot] = [hashFunction.create(), true]
) {
  hashUser(organization.boss, hashFunction, [state, false])
  if (isRoot) return hashFunction.digest(state);
}
freddi301 commented 2 years ago

If you find it useful i can try to write a pull request

marcj commented 2 years ago

@freddi301 cool idea! If we can get it very fast, we could replace the primary key hashing of the ORM https://github.com/deepkit/deepkit-framework/blob/master/packages/type/src/snapshot.ts#L153-L159

If you want to create a PR that would be cool