What is the best way to implement a mixin reducer for functional typing?

Currently, I am in the process of learning typescript and facing challenges in understanding how to correctly type a reducer function that reduces functional mixins.

Let's consider two functional mixins:

type FooComposable = {
  foo: string;
};
const withFoo = (composable): FooComposable => {
  composable.foo  = 'foo';

  return composable;
};

type BarComposable = {
  bar: string;
};
const withBar = (composable): BarComposable => {
  composable.bar = 'bar';

  return composable;
};

I have implemented a reducer function that will reduce all provided functional mixins:

const reduce(...fns) = fns.reduce((acc, fn) => fn(acc), {}));

reduce(withFoo); // -> { foo: 'foo' }
reduce(withBar); // -> { bar: 'bar' }
reduce(withFoo, withBar); // -> { foo: 'foo', bar: 'bar' }

My main concern is adding typings to the reduce() function (and functional mixins) in order to ensure that a reduced composable has the expected type inferences.

type FooComposable = {
  foo: string;
};
const withFoo = <T extends FooComposable>(composable: T): FooComposable => {
  composable.foo = 'foo';

  return composable;
};

type BarComposable = {
  bar: string;
};
const withBar = <T extends BarComposable>(composable: T): BarComposable => {
  composable.bar = 'bar';

  return composable;
};

type FunctionalMixin<T extends {}> = (composable: T) => T;
const reduce = <T extends {}>(...fns: FunctionalMixin<T>[]): T =>
  fns.reduce((acc, fn) => fn(acc), {});
/* Type '{}' is not assignable to type 'T'.
  '{}' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{}'.  */

reduce<FooComposable & BarComposable>(withFoo, withBar); // -> { foo: 'foo', bar: 'bar' }
/* Argument of type '<T extends FooComposable>(composable: T) => FooComposable' is not assignable to parameter of type 'FunctionalMixin<FooComposable & BarComposable>'.
  Type 'FooComposable' is not assignable to type 'FooComposable & BarComposable'.
    Property 'bar' is missing in type 'FooComposable' but required in type 'BarComposable'. */


Answer №1

Is there a way to enhance the reduce() function (as well as functional mixins) to ensure that the resulting reduced composable receives the expected type inferences?

In this scenario, the variable result correctly deduces the type as Foo & Bar.

Interactive Playground

type Foo = {
    foo: string;
};

const withFoo: Mixin<Foo> = (a) => ({ ...a, foo: 'foo' });

type Bar = {
    bar: string;
};

const withBar: Mixin<Bar> = (a) => ({ ...a, bar: 'bar' });

type Mixin<B> = <A extends object>(a: A) => A & B;

type Reduce<A extends object, T extends unknown[]> =
    T extends [] ? A :
    T extends [Mixin<infer B>, ...infer C] ? Reduce<A & B, C> :
    never;

const reduce = <T extends Mixin<unknown>[]>(...fns: T): Reduce<{}, T> =>
    fns.reduce((a, fn) => fn(a), {}) as Reduce<{}, T>;

const result = reduce(withFoo, withBar);

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

The type 'Promise<void>' is lacking the properties that are required by the type

I am having difficulty understanding the error message that says: The type 'Promise<void>' is missing the following properties from type 'InventoryModel[]': length, pop, push, concat, and 28 more. TS2740 Below is my functional co ...

Strategies for sending checkbox data to MySQL via AJAX and jQuery

Looking for assistance on passing values of multiple checkboxes to MySQL using arrays with AJAX (jQuery). I've written two separate code snippets, is there someone who can help me merge them? $(document).ready(function(){ var selected = []; $(&apo ...

An issue with jQuery's :not selector and hash symbol syntax

I encountered a syntax error that is quite charming. It appears when attempting to select all anchor tags without an href attribute containing a placeholder URL, such as href="#". Here are the attempts I have made: $("a:not(href='#')"); // cha ...

"Encountering a 500 internal server error with jQuery and WordPress

I'm having issues implementing ajax into my WordPress project to dynamically load videos based on their post ID. Whenever I click on the video link, a 500 internal server error occurs. I'm sending the post ID through ajax to a PHP script where I ...

Guide for receiving client messages on the server side (Node.js) with PubNub

How can I implement message communication between clients and servers using PubNub? Is it possible to subscribe to a channel on the server side (Node.js) and listen for messages? I need to utilize PubNub for the following scenario: => There are numer ...

Create a fresh type by dynamically adjusting/filtering its attributes

Suppose we have a type defined as follows: type PromiseFunc = () => Promise<unknown>; type A = { key1: string; key2: string; key3: PromiseFunc; key4: string; key5: PromiseFunc; key6: SomeOtherType1[]; key7: SomeOtherType2[]; key8: ...

The dimensions on Next.js pages exceed those of the viewport by a significant margin

I have recently encountered a perplexing issue where the dimensions of my webpage appear to be 2.7 times larger than the viewport, even when there is no content or styles applied. The strange part is that it seems as though the page has been scaled up, eve ...

Navigating Errors within Nested Promises: A Clear Perspective

Struggling with my first node.js backend, I am currently refactoring the login function. However, I seem to be missing something crucial when it comes to promise chaining and error handling. If anyone could help me identify where I'm going wrong, I wo ...

Encountering "net::ERR_EMPTY_RESPONSE" error when making a HTTP PUT request using the HUE API in JavaScript

GET requests are functioning properly. PUT requests made from the API Debug tool are also working correctly. However, both PUT and POST requests, regardless of the data or API URL used, are resulting in the following error: example: OPTIONS net::ERR_ ...

Is the `visibility: hidden` property not functioning as expected?

I am trying to conceal the script for the photoset until it is fully loaded, but unfortunately the code below does not seem to be effective: JavaScript $('.photoset-grid').photosetGrid({ rel: $('.photoset-grid').attr("data-id"), gutte ...

Can you explain the concept of ".el" as it relates to JavaScript, HTML, and jQuery?

After conducting a search on Google, I didn't find much information. Perhaps I am using the wrong terms. I am trying to figure out what the "el" in "$.el" represents in the following code snippet: $.el.table( $.el.tr( $.el.th('first name ...

Tips on accessing information from a JSON file

I am facing an issue while trying to extract data from a JSON object that was passed from the servlet. The keys in my JSON object are numbered, and I need to append these numbers to the names of the keys. The structure of my response is as follows: {"sha ...

Progress Bars Installation

For more detailed information, visit: https://github.com/rstacruz/nprogress After linking the provided .js and .css files to my main html file, I am instructed to "Simply call start() and done() to control the progress bar." NProgress.start(); NProgress. ...

Using Angular 2 to fetch barcode scanner information without the need for HTML input or textarea elements

Currently, I am in the process of developing a web application that utilizes a barcode scanner, specifically the Motorola TC55 model. My primary objective is to scan product EAN codes without the need for using HTML input or textarea elements. The reasoni ...

What is the best way to display a Bootstrap alert above all other elements on the page?

I need help with adjusting the placement of my bootstrap alert. Currently, when the input box value is not valid and the button is clicked, the alert shows up below the input box. I would like it to appear in the middle of the page, on top of the text box. ...

What is the process for initiating a state transition?

I have created two separate components. One component uses v-navigation-drawer, while the other component contains a button that toggles the state of the v-navigation-drawer using vuex. On smaller screens, when clicking on the gray area to close the navig ...

Can TypeScript modules be designed to function in this way?

Seeking to create a versatile function / module / class that can be called in various ways: const myvar = MyModule('a parameter').methodA().methodB().methodC(); //and also this option should work const myvar = MyModule('a parameter') ...

AJAX chat application's updating frequency

As I work on building a website that includes a feature for real-time chatting between users (similar to Facebook chat), I have implemented a system where messages are stored in a MySQL table called messages. This table contains the message ID, sender ID, ...

The XML information vanished during the transformation into JSON format

After converting XML to JSON using multiple conversion libraries, I noticed that the property name attributes and Item name attributes were lost. Why is this happening? Does anyone have suggestions on how I can modify my XML to make it more compatible for ...

Tampermonkey feature: Extract source code with a button click from a constantly updating AJAX page

My goal is to create a simple script that can copy the source code of a dynamic AJAX page whenever I press a button. The current code, which I have included below, seems to be working fine: // ==UserScript== // @require http://ajax.googleapis.com/ajax/li ...