Bundle with no crucial dependencies

In need of creating a package that offers abstractions relying on the IObservable interface, I require two external classes mimicking the behavior of Subject<T> and BehaviorSubject<T> from rxjs.

However, it is essential for me to avoid tightly coupling my package with rxjs. I aim to make it compatible with other packages implementing these interfaces as well.

I have devised this particular solution. While it serves my needs, I am curious about whether I can rely on the behavior of the import statement.

This stems from my understanding that imports are hoisted and executed asynchronously. What if, in some scenarios, myLibrary is imported before rxjs and global setup?

EDIT:

My decision was to utilize an init({Subject, ...other_types}) function, which I have incorporated into the updated gist in the provided link. The workflow now follows this pattern:

import {some_types} from 'some_package'
import {init} from 'myLib'

init(some_types)

// ... allowing the consumer to import additional functionalities from myLib

Although I still ponder over the sequencing of imports, that is a story for another time...

Answer №1

Implementing SOLID principles can be beneficial:

  • Interface segregation → creating specific interfaces for your requirements, such as Subject<T> and BehaviorSubject<T>, tailored to your needs.
  • Dependency inversion → relying on abstract types rather than direct RxJs dependencies can help decouple the application from RxJs.
  • TypeScript's structural typings support allows for compatibility between interfaces and RxJs types, enabling these interfaces to serve as dependencies in your application. If compatibility is lacking, creating wrappers becomes necessary.

By using ES6 modules with static imports, modules will load correctly in sequence (barring any unusual configurations with module loaders or bundlers). In the example below, RxJs cannot be loaded after subjects.ts:

// -- subjects.ts ----
export interface Subject<T> { /*...*/ }
export interface BehaviorSubject<T> { /*...*/ }

// -- create-subjects.ts ----
import * as rx from 'rxjs/Rx';
import { Subject, BehaviorSubject } from './subjects.ts';

// Subject<T> and rx.Subject<T> are compatible
export function createSubject<T>(): Subject<T> {
    return new rx.Subject<T>();
}

// BehaviorSubject<T> and rx.BehaviorSubject<T> are not compatible => wrapper
export function createBehaviorSubject<T>(value: T): BehaviorSubject<T> {
    const wrappee = new rx.BehaviorSubject(value);
    return {
        suscribe: (callback: Function) => wrappee.suscribe(callback),
        /*...*/
    };
}

// -- consumer.ts ----
import { createSubject } from './create-subjects.ts';

const subject = createSubject<string>();
// ...

Transitioning to another stream library becomes easier by simply modifying one file: create-subjects.ts, assuming that the custom XxxSubject interfaces have been well-designed to meet the specific needs of the application (which is not elaborated upon in the current context).

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

A Guide to Iterating Through Arrays of Objects Using TypeScript

Currently, I am engrossed in an Angular project where I am fetching an object containing an array of objects from an API. The object being passed to the API as a parameter through my service is called "reportData". Here is an example of the data retrieve ...

Develop a customized interface for exporting styled components

I am struggling to figure out how to export an interface that includes both the built-in Styled Components props (such as as) and my custom properties. Scenario I have created a styled component named CustomTypography which allows for adding typographic s ...

Troubleshooting offline pagination with dynamic MatTable containing matInputs (Angular 5 Material Design)

I have an issue with my component that contains an empty form with matInputs, as well as a mat-table with matInputs in the rows, all enclosed in mat-cards. The number of rows in the table is dynamic and based on another input called 'range'. So, ...

Leveraging the Cache-Control header in react-query for optimal data caching

Is it possible for the react-query library to consider the Cache-Control header sent by the server? I am interested in dynamically setting the staleTime based on server instructions regarding cache duration. While reviewing the documentation, I didn&apos ...

Vue 3 does not maintain derived property values when assigning them to an object value

I have been facing a challenge while trying to set up an object for the Ionic Capacitor Google Maps API in order to configure the map upon creation. The issue I am encountering is that the value of the reference I am using is not persistent and keeps rever ...

Ways to change a value into int8, int16, int32, uint8, uint16, or uint32

In TypeScript, the number variable is floating point by default. However, there are situations where it's necessary to restrict the variable to a specific size or type similar to other programming languages. For instance, types like int8, int16, int32 ...

Utilizing Typescript's conditional type to determine behavior based on the specific value of a string literal type

I'm currently figuring out how to define a conditional type in typescript based on a predefined string literal Let me walk you through an example to clarify. To provide some context, users are required to categorize data from images, where there are ...

Unlocking the ability to retrieve data generated by the context within getServerSideProps beyond its boundaries (for transitioning from Create React App to Next.js)

I am currently utilizing Create React App for my react application but I am in the process of migrating to Next.js. Accessing URL data such as host, protocol, and query parameters has posed a significant challenge. After some trial and error, I realized t ...

The error message "TypeError: text is not a function" is displayed when trying to utilize the text() method from either Blob

My current dilemma revolves around the usage of functions defined in the typescript lib.dom.d.ts file within my node.js express backend that is implemented using TypeScript. Specifically, I am encountering issues with the File/Blob interfaces where a File ...

The Typescript compiler is unable to ignore imported JavaScript files

Recently, I started working with TypeScript and Angular 2, but encountered a problem that has left me puzzled. Initially, everything was going smoothly with the angular2 quickstart project until I attempted to import a plain JavaScript file. import * as m ...

Encountering Typescript issues following the transition from npm to pnpm

Currently, I am facing a challenge in migrating an outdated Angular JS project from npm to pnpm. The main issue I am encountering is related to typescript errors, particularly the error message that states: error TS2339: Property 'mock' does not ...

Loading data synchronously in Angular6 routes

After recently integrating Server-Side Rendering (SSR) into my Angular6 application to render dynamic HTML in a crawlable manner, everything appears to be functioning properly. But I am facing an issue when trying to render data from an API endpoint. Upon ...

When 'Interval.after' is invoked within the library, Luxon throws an error message stating "Invalid Interval."

Encountering a strange issue with Luxon when the Interval.after method is invoked within the library. const interval = Interval.after(dateTime, duration); The following log pertains to the application DateTime__Duration, with the second line representing ...

Angular - personalized modal HTML

I am facing a challenge where I need to trigger a popup when a button is clicked. There can be multiple buttons, each with its own overlay popup, and these popups should close when clicking outside of them. Currently, I am using TemplateRef (#toggleButton ...

Retrieve the data from the mat-checkbox

My goal is to retrieve a value from a mat-checkbox, but the issue is that we only get boolean expression instead of the string value. Here's an example snippet of what I'm looking for: <mat-checkbox formControlName="cb2" <strong&g ...

Steps for setting up a nested route in Angular 2

I am currently working on a project that includes an admin page (check the file structure below). I am trying to set up a child route named 'createuser' for the admin page (localhost:4200/admin/createuser). Despite my attempts, I encountered an e ...

Response received through GET call in text format

Implementing a typed response in a simple GET request seems to be causing a strange behavior in the compiler. The application compiles successfully, but a red error is returned with the message displayed in the VS Code screenshot below: ERROR in src/app/s ...

Using TypeScript with Mongoose: Issue with finding documents conditionally on model results in error: Union type signatures are not compatible

Seeking assistance on how to conditionally access a mongoose model in TypeScript code. Does anyone have a solution to resolve this TypeScript error? Each member of the union type has signatures, but none of those signatures are compatible with each other ...

Learn how to define an object with string keys and MUI SX prop types as values when typing in programming

I want to create a comprehensive collection of all MUI(v5) sx properties outside of the component. Here is an example: const styles = { // The way to declare this variable? sectionOne: { // What type should be assigned here for SXProps<Theme>? } ...

Handlebar files are not compatible with Typescript loading capabilities

I am encountering an issue with my directory structure as follows : src |- server |- myServer.ts |- views |- myView.hbs dist |- server |- myServer.js The problem lies in the fact that the dist folder does not have a views subfolder, where the J ...