Exploring Typescript: Combining types (rather than intersecting them)

Let's analyze the scenario below

type MergeFn = <K1 extends string, V1, K2 extends string, V2>(
   k1: K1, v1: V1,
   k2: K2, v2: V2
) => ???

let mergeFn: MergeFn // actual implementation doesn't matter for this question

What should be replaced in place of ??? so that

mergeFn(
  "hello", 1,
  "typescript", 2
)

results in

{ hello: number, typescript: number }
.

I attempted to use

??? = { [k in K1]: V1 } & { [k in K2]: V2 }

however, it only yields

{ hello: number } & { typescript: number }
.

(Even applying

type Id<T> = { [k in keyof T]: T[k] }
as suggested here did not provide a solution.)

Try out the example in the TypeScript playground

Answer №1

If you want to simplify the process, consider using a single conditional mapped type instead of an intersection:

type CombineFn = <Key1 extends string, Value1, Key2 extends string, Value2>(
    key1: Key1, value1: Value1,
    key2: Key2, value2: Value2
) => { [K in Key1 | Key2]: K extends Key1 ? Value1 : Value2}

This will generate:

const example = combineFn(
    "hello", 6,
    "world", 3
)
/* const example: {
    hello: number;
    world: number;
} */

If you found that Id<T> didn't provide the expected outcome, you can bypass it by introducing an intermediate conditional type like so:

type Extract<T> = T extends infer U ? { [K in keyof U]: U[K] } : never

Using this with your initial code:

type CombineFn = <Key1 extends string, Value1, Key2 extends string, Value2>(
    key1: Key1, value1: Value1,
    key2: Key2, value2: Value2
) => Extract<Record<Key1, Value1> & Record<Key2, Value2>>

You'll get the same result as before:

const example = combineFn(
    "hello", 6,
    "world", 3
)
/* const example: {
    hello: number;
    world: number;
} */

Both methods should work for you.


Hopefully this guidance proves useful! Best of luck!

Link to code

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

tips on how to export an object with a specified data type

I need to restrict the type of exported function for my module type Request = ItemGetRequest | ItemUpdateRequest<Property> type Response = Property | ItemUpdateResponse<Property> type Handlers = {[key: string]: Handler<Request, Response> ...

Identifying and handling errors in the outer observable of an RXJS sequence to manage

Encountered a puzzling rxjs issue that has me stumped. Here's the scenario: I have two requests to handle: const obs1$ = this.http.get('route-1') const obs2$ = this.http.get('route-2') If obs1$ throws an error, I want to catch it ...

Rxjs error: The 'pipe' property is not found on the 'UnaryFunction<Observable<{}>, Observable<string | {}>>' type

Currently working on implementing ngbTypeAhead and encountering problems with RxJS version 5.5.5. The example I am referencing is from version 6 of rxjs. "rxjs": "^5.5.2" and angular "^5.0.1", "typescript": "~2.6.1", While trying to apply typeahead on f ...

Utilizing a conditional ngIf statement in HTML or incorporating a variable within typescript for logical operations

When working with our application, we often need to display or hide a button based on specific logic. Where do you think it is best to define this logic and why? In HTML: *ngIf='logic goes here' //Or *ngIf='someBoolean' and in Type ...

Node.js does not allow the extension of the Promise object due to the absence of a base constructor with the required number of type

I'm trying to enhance the Promise object using this code snippet: class MyPromise extends Promise { constructor(executor) { super((resolve, reject) => { return executor(resolve, reject); }); } } But I keep encou ...

Is there a way to compile Node's global modules and objects using TypeScript while having the checkJs option enabled?

By including "checkJs": true in my tsconfig.json file, Node's global paths and objects are marked as "not found". For example, if I were to write: import path from "path"; const p = path.resolve(__dirname, 'dist/js') The TypeScript co ...

Substitute Customized Interface Type Identifier

I am working on creating a versatile function interface for functor map while respecting the provided interface. In the code snippet below, my goal is to ensure that the value of mb is of type Maybe<number>, rather than the actual type Functor<num ...

Is it possible to build a Node.js (Express) application using a combination of JavaScript and TypeScript?

Currently, I have a Node.js project (Express REST API) that is written in JavaScript. My team and I have made the decision to gradually rewrite the entire project into TypeScript. Is it possible to do this incrementally, part by part, while still being ab ...

An array of objects in Typescript utilizing a generic type with an enum

Here’s a glimpse of code that showcases the issue: enum ServicePlugin { Plugin1, Plugin2, Plugin3, } interface PluginOptions { [ServicePlugin.Plugin1]: { option1: string }; [ServicePlugin.Plugin2]: { option1: number; option2: number }; } type ...

Typescript and MomentJS integration - What is the data type of the moment() function?

Currently in the process of upgrading my project from ES5 to ES6, I've encountered a problem with MomentJS (version 2.18.1). The issue arises when dealing with variables that are Moment objects and the inability to call moment() on them. For instance ...

Oops! Looks like there's a type error in module "*.mdx" - it seems that it doesn't have the exported member "metadata". Maybe try using "import metadata from "*.mdx"" instead?

I am attempting to extract metadata from an mdx file. I have followed the guidelines outlined in NextJS Markdown Frontmatter, but encountered build errors. It is important to note that I am unable to utilize fs. Code Section Page.tsx File import Conte ...

Utilize Typescript/Javascript to utilize the Gmail API for sending emails via email

I am trying to send emails from my application using my Gmail account with Ionic. I have followed tutorials from SitePoint and Google Developers. Here is how I'm initializing the client: client_id: gapiKeys.client_id, discoveryDocs: ["https://www.goo ...

Using TypeScript with Angular, you can easily include parameters to HTML tags

I have an HTML element that looks like this: eventRender(info){ console.log(info.el); } This is the output I'm seeing: https://i.stack.imgur.com/G0hmw.png Now, I want to include these attributes: tooltip="Vivamus sagittis lacus vel augue ...

typescript leaflet loading tutorial

I'm attempting to replicate the basic example of loading a map with Leaflet in TypeScript, following the guidance on the Leaflet website. I am not utilizing any frameworks like Angular or React. I have installed Leaflet and types through npm. To adher ...

The access to the HTTP response object is not possible: the property is not found on the Object type

I recently created a response object and assigned it to the "this" object. However, when I try to access the datacentersinfo property, I encounter an error stating that the property does not exist on type Object. Due to this issue, I am unable to generat ...

Creating personalized functions in Object.prototype using TypeScript

My current situation involves the following code snippet: Object.prototype.custom = function() { return this } Everything runs smoothly in JavaScript, however when I transfer it to TypeScript, an error surfaces: Property 'custom' does not ex ...

Utilizing constants within if statements in JavaScript/TypeScript

When working with PHP, it is common practice to declare variables inside if statement parenthesis like so: if ($myvar = myfunction()) { // perform actions using $myvar } Is there an equivalent approach in JavaScript or TypeScript?: if (const myvar = myf ...

Sometimes encounter undefined values after assigning them through the service

One of the challenges I am facing is handling public fields in my service: @Injectable() export class ShareDataService { // Some code public templateForCurrencyCOS; public templateForPercentCOS; public templateForCurrencyCOGS; public te ...

Discover the step-by-step process for moving data between collections in MongoDB

I am currently working on nestjs and have two collections, one for orders and the other for payments. My goal is to retrieve a single entry from the orders collection and save that same entry into the payments collection. Below is the code for the service ...

Is there an improved method for designing a schema?

Having 4 schemas in this example, namely Picture, Video, and Game, where each can have multiple Download instances. While this setup works well when searching downloads from the invoker side (Picture, Video, and Game), it becomes messy with multiple tables ...