From 043b86d9bfe7e21fca25c6781de42d96c109ac80 Mon Sep 17 00:00:00 2001 From: Antonio Barcelos Date: Tue, 8 Nov 2022 11:07:36 +0100 Subject: [PATCH] Add generic types for Node#labels, Relationship#type and UnboundRelationship#type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This generic types enable defining a list string like values accepted for an specific node labels list or relationship type. Node example: ```typescript type PersonLabels = 'Person' | 'Actor' // get the person from a non-typed record. If the record is correctly type-mapped // the Node type can be omitted since it will be inferred. const person: Node = record.get('person') // get labels // the type inferred for the labels will be PersonLabels[] const labels = person.labels // @ts-exepct-error const wrongLables: 'Car'|'Bicycle'[] = person.labels ``` Relationship/UnboundRelationship example: ```typescript type ActedInType = 'ACTED_IN' // get the relationship from a non-typed record. If the record is correctly type mapped // the Relationship type can be omitted since it will be inferred. const actedIn: Relationship = record.get('actedIn') // get type // the type inferred for the relType will be 'ACTED_IN' const relType = actedIn.type // @ts-expect-error const directed: 'DIRECTED' = actedIn.type ``` ⚠️ This type definitions are not asserted in runtime. Thus mismatched type records coming from the database will not trigger type errors. --- packages/core/src/graph-types.ts | 18 ++++----- packages/core/test/graph-types.test.ts | 40 +++++++++++++++++++ .../neo4j-driver-deno/lib/core/graph-types.ts | 18 ++++----- 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/packages/core/src/graph-types.ts b/packages/core/src/graph-types.ts index 03c0ff859..85736bb49 100644 --- a/packages/core/src/graph-types.ts +++ b/packages/core/src/graph-types.ts @@ -47,9 +47,9 @@ function hasIdentifierProperty (obj: any, property: string): boolean { /** * Class for Node Type. */ -class Node { +class Node { identity: T - labels: string[] + labels: Label[] properties: P elementId: string /** @@ -60,7 +60,7 @@ class Node { +class Relationship { identity: T start: T end: T - type: string + type: Type properties: P elementId: string startNodeElementId: string @@ -147,7 +147,7 @@ class Relationship { +class UnboundRelationship { identity: T - type: string + type: Type properties: P elementId: string @@ -250,7 +250,7 @@ class UnboundRelationship { expect(isNode(nonNode)).toBe(false) }) + test('should type mapping labels', () => { + type PersonLabels = 'Person' | 'Actor' + const labels: PersonLabels[] = ['Actor', 'Person'] + type Person = Node + + const p: Person = new Node(1, labels, {}) + + const receivedLabels: PersonLabels[] = p.labels + + expect(receivedLabels).toEqual(labels) + + // @ts-expect-error + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const _: 'Movie'|Array<'TvShow'> = p.labels + }) + function validNodes (): any[] { return [ [new Node(1, ['label'], {}, 'elementId')], @@ -191,6 +207,18 @@ describe('Relationship', () => { expect(isRelationship(nonRelationship)).toBe(false) }) + test('should type mapping relationship type', () => { + type ActedIn = Relationship + const a: ActedIn = new Relationship(1, 1, 2, 'ACTED_IN', {}) + + const receivedType: 'ACTED_IN' = a.type + expect(receivedType).toEqual('ACTED_IN') + + // @ts-expect-error + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const _: 'DIRECTED' = a.type + }) + function validRelationships (): any[] { return [ [new Relationship(1, 2, 3, 'Rel', {}, 'elementId', 'startNodeElementId', 'endNodeElementId')], @@ -306,6 +334,18 @@ describe('UnboundRelationship', () => { ) }) + test('should type mapping relationship type', () => { + type ActedIn = UnboundRelationship + const a: ActedIn = new UnboundRelationship(1, 'ACTED_IN', {}) + + const receivedType: 'ACTED_IN' = a.type + expect(receivedType).toEqual('ACTED_IN') + + // @ts-expect-error + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const _: 'DIRECTED' = a.type + }) + function validUnboundRelationships (): any[] { return [ [new UnboundRelationship(1, 'Rel', {}, 'elementId')], diff --git a/packages/neo4j-driver-deno/lib/core/graph-types.ts b/packages/neo4j-driver-deno/lib/core/graph-types.ts index 8ec873917..618732f70 100644 --- a/packages/neo4j-driver-deno/lib/core/graph-types.ts +++ b/packages/neo4j-driver-deno/lib/core/graph-types.ts @@ -47,9 +47,9 @@ function hasIdentifierProperty (obj: any, property: string): boolean { /** * Class for Node Type. */ -class Node { +class Node { identity: T - labels: string[] + labels: Label[] properties: P elementId: string /** @@ -60,7 +60,7 @@ class Node { +class Relationship { identity: T start: T end: T - type: string + type: Type properties: P elementId: string startNodeElementId: string @@ -147,7 +147,7 @@ class Relationship { +class UnboundRelationship { identity: T - type: string + type: Type properties: P elementId: string @@ -250,7 +250,7 @@ class UnboundRelationship