Tips for crafting a TypeScript function signature for a bijection-generating function

One of my functions involves taking a map and generating the bijection of that map:

 export function createBijection(map) {
  const bijection = {};
  Object.keys(map).forEach(key => {
    bijection[key] = map[key];
    bijection[map[key]] = key;
  });
  return bijection;
}

What is an elegant way to define the signature of this function in TypeScript?

Answer №1

To simplify the process of converting a type like

{a: "A", b: "B"}
to its inverse,
{A: "a", B: "b"}
, TypeScript 4.1 introduces the use of mapped type as clauses as shown in microsoft/TypeScript#40336:

// TS4.1+
type Invert<T extends Record<keyof T, PropertyKey>> = { [K in keyof T as T[K]]: K };

For TypeScript versions before 4.1, a similar effect can be achieved using mapped conditional types:

// TS4.0-
type Invert<T extends Record<keyof T, PropertyKey>> =
    { [K in T[keyof T]]: { [P in keyof T]: K extends T[P] ? P : never }[keyof T] }

In both cases, the goal is for keyTextBijection to take an object of type T and return an object of type T & Invert<T>. To make this merge look cleaner, the no-op mapped type Id is defined to achieve this:

type Id<T> = T extends infer U ? { [K in keyof U]: U[K] } : any;

The function signature for keyTextBijection is setup with a single overload call that allows for greater flexibility with type safety using any.


A test case is provided to validate the implementation:

const bij = keyTextBijection({ a: "A", b: "B", c: "C" });
/* const bij: {
    a: "A";
    b: "B";
    c: "C";
    A: "a";
    B: "b";
    C: "c";
} */
console.log(bij);
/* {
  "a": "A",
  "A": "a",
  "b": "B",
  "B": "b",
  "c": "C",
  "C": "c"
}  */

The results seem accurate based on the values passed in.


Playground 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

How to disregard the "Declaration not found" error while using VS Code with TypeScript

Working with Typescript and Vue Cli in VS Code, I encountered a "definition missing warning" at this particular line: import { setupCalendar, DatePicker } from "v-calendar"; The issue states: Could not find a declaration file for module 'v-calen ...

Guide to utilizing vue-twemoji-picker in TypeScript programming?

Has anyone encountered this issue when trying to use vue-twemoji-picker in a Vue + TypeScript project? I keep receiving the following error message. How can I fix this? 7:31 Could not find a declaration file for module '@kevinfaguiar/vue-twemoji-picke ...

React application facing a problem with bracket notation in Typescript

After creating a form state to store and update input changes, I encountered an issue: const [form, setForm] = useState({ user: '', email: '', password: '', }); I then wrote a function to handle form changes: const handle ...

Get rid of the strange border on the material dialog

I am struggling with the Angular material 6 dialog component as it is displaying a strange border. I have attempted to remove it using the code below, without success. Interestingly, when I apply the style inline in the browser, it works fine. Any suggesti ...

Dealing with Typescript (at-loader) compilation issues within a WebPack environment

Currently, I am using Visual Studio 2017 for writing an Angular SPA, but I rely on WebPack to run it. The current setup involves VS building the Typescript into JS, which is then utilized by WebPack to create the build artifact. However, I am looking to t ...

Fastify Schema Failing to Validate Incoming Requests

Currently, our backend setup involves using Node.js and the Fastify framework. We have implemented a schema in satisfy to validate user input. Below is the schema defined in schema.ts: export const profileSchema = { type: 'object', properti ...

Unable to implement multiple draggable inner objects using Angular 5 and dragula library

After struggling for the past few days, I can't seem to get it to work... Here is a brief explanation of my issue: In this example, I have an array of objects structured like this: public containers: Array<object> = [ { "name": "contain ...

Changing a complex object within a nested array of a BehaviorSubject

I'm currently working on an Angular app. Within my service, DocumentService, I have a BehaviorSubject that holds an array of Documents. documents: BehaviorSubject<Document[]> Let me provide you with some insight into the various classes I' ...

I am unable to display the service response in the Angular component

I'm facing an issue with displaying data in an angular component from a service. The process from the service to the component seems fine, but when I try to use the variable in HTML, it doesn't show the result. For this project, I am using the M ...

Is it time to refresh the sibling element when it's selected, or is there

I have recently started working with react and TypeScript, and I am facing some challenges. My current task involves modifying the functionality to display subscriptions and transactions on separate pages instead of together on the same page. I want to sh ...

Incorrect types being identified

What is the reason behind the callback assuming the type string | number | boolean instead of determining the exact type based on the property passed as the first argument in the carWithListener.on function? const car = { paint: "red", ...

What is the best way to utilize TypeScript module augmentation with material-ui components?

I have gone through the answers provided in this source and also here in this link, but it appears that they are outdated. I attempted to enhance the type definition for the button component in various ways, including a separate typings file (.d.ts) as we ...

There are no imports in index.js and there is no systemjs configuration set up

After creating a fresh Angular project using ng new some-name, I noticed that the generated index.html file does not include any <script> tags and there is no SystemJS configuration either. Is this the expected behavior? I was anticipating the CLI ...

The property 'toLowerCase' cannot be accessed as it is undefined or null

Scenario: A textbox is present with a list of data below it. Upon typing in the textbox, the list gets filtered based on the text entered. Code: Pipe: @Pipe({ name: 'search' }) export class SearchPipe implements PipeTransform { transform( ...

Avoid retrieving information from Firestore

Hey everyone, I'm struggling to figure out why I can't retrieve data from Firestore. Even after carefully reading the documentation and double-checking the path, I still can't seem to make it work. I'm working with Ionic framework. getC ...

The TypeScript type for a versatile onChange handler in a form

Let's skip the function declaration and dive into writing the current types for state, and the state itself. type BookFormState = { hasError: boolean; } BookForm<BookFormState> { ... state = { hasError: false }; Next, inside the class ...

React / NextJS: Repeating Audiowave Component

I am currently developing a chat application in NextJS that includes text-to-speech functionality. To visualize the audio playback waveform, I have integrated a third-party library called wavesurfer.js Though the audio implementation is functioning proper ...

Updating DynamoDB objects seamlessly in Lambda functions without any conflicts

I am currently working with example Objects that follow this interface structure: interface Car{ id: Number; name: String; tires: Wheel[] } interface Wheel{ id: Number; name: String; radius: Number; } My goal is to store these Car Objects in DynamoDB and ...

Guide on exporting a function from a module as a class property

How to export a function as a class property from a module? Even if modifiers such as public are added, when a class property points to a function within a module, it behaves as though it is private. There are multiple ways to define a property (a, b, c ...

Angular routing is showing an undefined ID from the snapshot

When a user attempts to update a student, I pass in the student ID. The update successfully redirects to the updateStudent page and displays the student ID in the browser link. However, within my app component, it shows as undefined. Student View componen ...