Skip to content

feat: TermWrapper.from static factory with intersection return type#83

Draft
jeswr wants to merge 1 commit into
rdfjs:mainfrom
jeswr:feat/term-wrapper-from
Draft

feat: TermWrapper.from static factory with intersection return type#83
jeswr wants to merge 1 commit into
rdfjs:mainfrom
jeswr:feat/term-wrapper-from

Conversation

@jeswr

@jeswr jeswr commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Adds an overloaded public static from(term, dataset, factory) factory to TermWrapper.

What it does

  • from(term: string, dataset, factory) returns InstanceType<This> & NamedNode<string>
  • from(term: T extends Term, dataset, factory) returns InstanceType<This> & T
  • The implementation is simply return new this(term, dataset, factory) — identical runtime behaviour to the constructor, so subclasses get the factory for free (Child.from(...) returns Child & NamedNode).

Because the return type intersects the wrapper with the RDF/JS term type, instances created via from can be passed directly to factory.quad(...), dataset.match(...) and any other Term position without casts — the pain point both #61 and #74 set out to fix.

What it deliberately does not do

This is the minimal, fully non-breaking slice: no generic parameter on TermWrapper, no getter restructuring, no IRdfJsTerm removal, no changes to the #subjectPredicate mapper signatures. The constructor and all existing typed getters are untouched, so existing code compiles unchanged.

Relation to existing PRs

Supersedes the TermWrapper.from slice of #74 (its from overloads and README updates are adopted here verbatim) and the #from slice of #61. The remaining parts of those PRs (#in, class-level generics, getter/IRdfJsTerm restructuring, mapper signature changes) are intentionally left for follow-ups.

Testing

  • New test/unit/term_wrapper_from.test.ts: runtime assertions (subclass instance creation, constructor equivalence for string and Term inputs, accessor/dataset/factory behaviour) plus compile-level assertions (result assignable to NamedNode/Quad_Subject; passed to DataFactory.quad and DatasetCore.match with no casts; Literal term type preserved).
  • npm test: 132 tests, 0 fail (5 pre-existing skips); new code at 100% coverage.
  • npx typedoc: 0 errors; the 6 warnings are all pre-existing on main.

Review timing: This draft was prepared with Claude; I (@jeswr) will personally review it before it progresses. I'm currently batching a lot of work in flight, so expect active review Wednesday-Friday (8-10 July).

Adds an overloaded public static from(term, dataset, factory) to
TermWrapper that is runtime-equivalent to the constructor but returns
the intersection of the (sub)class instance type and the RDF/JS term
type of the wrapped term (NamedNode when a string IRI is passed, the
inferred term type otherwise). Instances created this way can be passed
directly to factory.quad(), dataset.match() and any other RDF/JS Term
position without casts.

Fully non-breaking: the constructor and the existing typed getters are
untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant