Skip to content

Improve Typings for query.execute #175

@jameslaneconkling

Description

@jameslaneconkling

It would be nice if functions like execute returned typed results. Some potential steps towards that could be:

  • make the HTTP.Body generic:
type SuccessBody<T> = {
    status: number;
    statusText: string;
    headers: Headers;
    url: string
    ok: true;
    body: T;
}
    
type ErrorBody = {
    status: number;
    statusText: string;
    headers: Headers;
    url: string
    ok: false;
    body: {
        message: string,
        code: string
    };
}
    
export type Body<T = any> = SuccessBody<T> | ErrorBody

By making Body a tagged union of success and error types, a type guard can properly narrow Body based on the ok key:

const handleResponse = (res: HTTP.Body<SomeResponseType>) => {
  if (!res.ok) {
    return console.error(res.body.message); // res.body is of type { message: string, code: string }
  }
  console.log(res.body); // res.body is SomeResponseType
};

With that in place, execute could look something like:

type RDFIRITerm = { type: 'uri', value: string }
type RDFLiteralTerm = { type: 'literal', value: string, 'xml:lang'?: string, datatype?: string }
type RDFBlankTerm = { type: 'bnode', value: string }
type RDFTerm = RDFIRITerm | RDFLiteralTerm | RDFBlankTerm

type SPARQLSelectResult<Variable extends string> = {
    head: {
        vars: Variable[]
        link: string[]
    }
    results: {
        bindings: Array<{ [V in Variable]: RDFTerm }>
    }
}

type SPARQLAskResult = {
    head: {},
    boolean: boolean
}

type SPARQLResult<Variable extends string> = SPARQLSelectResult<Variable> | SPARQLAskResult

function execute<Variable extends string = ''>(
    conn: Connection, database: string, query: string, accept?: HTTP.AcceptMimeType, params?: object
): Promise<HTTP.Body<SPARQLResult<Variable>>>;

and be used like

query.execute<"name" | "age">(
  conn,
  'myDB',
  'SELECT * WHERE { :personA :name ?name ; :age ?age }',
  'application/sparql-results+json'
)
  .then((res) => {
    if (!res.ok) {
      return console.error(res.body.message);
    }

    console.log(res.body.head) // res.body.head is of type {} | { vars: ("name" | "age")[], link: string[], }
  });

If this is of interest, I'd be happy to open a PR.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions