Techniques for a versatile class limited to a particular category

In my code, I have a Vector class that looks like this:

class Vector<N extends number> {...}

N represents the size or dimension of the vector. This Vector class also includes a cross product method to calculate the cross product between vectors:

cross(vector: Vector<N>) {...}

The issue is that the cross product method is only valid for vectors with 3 dimensions (N extends 3). So, my question is: Is there a way to prevent other vectors from accessing the cross product method, except for those with exactly 3 dimensions? I would prefer not to use a subclass such as 3DVector specifically for implementing the cross product method. One solution I considered is:

cross(vector: N extends 3 ? Vector<3> : never) {...}

However, this solution does not completely hide the method but rather disables it by setting the parameter to never. Can you suggest a better approach to solve this problem more effectively?

Answer №1

To enhance the functionality of the Vector class, you can create a specialized subclass called Vector3D. This subclass can include methods specific to 3-dimensional vectors, such as the cross method. By doing this, you essentially "hide" the method from other types of vectors.

export class Vector<N extends number> {
    /* ... */
}

export class Vector3D extends Vector<3> {
    cross(vector: Vector3D) {
        /* ... */
    }
}

export class Vector2D extends Vector<2> {
    /* ... */
}

const vectorWithCross = new Vector3D();
const vectorWithoutCross = new Vector2D();
const genericVector = new Vector<390>();

vectorWithCross.cross(new Vector3D()) // works fine

vectorWithoutCross.cross(new Vector3D()) // error
genericVector.cross(new Vector3D()) // error

Feel free to experiment with this code on TypeScript playground for further customization.

Answer №2

Imagine a scenario where you were not utilizing generics, but instead creating classes like Vector1d, Vector2d, Vector3d, etc. In this situation, if the cross operation is only applicable to Vector3d, you would exclude it from the other classes and attempt to conceal it -- for example, by adding the method in the derived class if they all inherit from Vector.

Similarly, I believe that if a method pertains solely to a specific value of the generic type, it should not be part of the generic's methods.

Although I do not have enough knowledge of TypeScript to provide a precise solution, generally speaking, I think that cross should exist as a global or standalone function, rather than being contained within the class:

class Vector<N extends Number> { ... };

// ...

function cross(Vector<3>, Vector<3>) -> Vector<3>;

Alternatively, you could establish a separate class specifically for 3D vectors and implement the operation there:

class Vector<N extends Number> { ... };

// ...

class Vector3D extends Vector<3> {
  // ...
  function cross(Vector3D, Vector3D) -> Vector3D { 
   // ....
  }
}

Answer №3

Here is a solution that may not be perfect, but it's worth trying out.

// Creating a vector class with a missing cross method
class vector<N extends number>{...}

// Manually adding the cross method to the prototype
vector.prototype.cross = function (other: vector<3>) {...}

// Re-defining the vector interface with the added cross method, demonstrating how TypeScript interfaces can be extended
interface vector<N extends number>{
    cross: (N extends 3 ? (other: vector<3>) => vector<3> : never)
}

The key aspect here is the type definition of the cross method, which is dependent on the type argument provided. If the type is 3, then cross is available as a method; otherwise, it's set to never. This ensures that while autocomplete may still display cross when N is not 3, it won't be callable in those cases.

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 for acquiring the newest router in an angular environment

Is there a way to retrieve and store the URL of the latest router that the user has visited in local storage? Any suggestions would be greatly appreciated. Thank you! ...

Encountering difficulty in removing a record from the database utilizing Prisma with Next.js API routes

Currently, I am in the process of developing a Todo manager using Next.js 13, Prisma, and MySQL. In order to include a feature that allows users to delete a todo item, I have implemented the use of a Link tag for the delete button within my code: ... <L ...

What is the best way to transform a JS const into TSX within a Next.js application?

Exploring the code in a captivating project on GitHub has been quite an adventure. The project, located at https://github.com/MaximeHeckel/linear-vaporwave-react-three-fiber, showcases a 3D next.js application that enables 3D rendering and animation of mes ...

What is the correct way to add type annotations to an Axios request?

I have meticulously added type annotations to all endpoints in my API using the openapi-typescript package. Now, I am looking to apply these annotations to my Axios requests as well. Here is a snippet of code from a Vue.js project I have been developing: ...

Locating a class variable using a string chosen from a DropDown menu

In my Tv class, I have several string variables. One requirement is for the user to select an option from a DropDown list and input a value. This entered value should then be stored in the Tv class under a variable with a similar name to the selected optio ...

Executing a designated assessment in Protractor

Is there a way to run a specific test scenario in my Angular app? I recently added a new feature in Protractor, created the necessary page and steps, but I already have other features implemented. I am wondering if it is possible to solely test the new f ...

Is there a way to install @types that are compatible with an outdated version of TypeScript?

I am currently working on a project that relies on packages such as @types/express and @types/body-parser. The problem is, the recent updates to these .d.ts files have introduced generic defaults, which now require TypeScript 2.3 or higher. Unfortunately, ...

How to send form group in Angular when the enter key is pressed

When I press the submit button on a form, it sends a request to the database to filter data in a grid. However, I also want the form to submit when the enter key is pressed. HTML <form [formGroup]="bmForm" (keyup.enter)="onSearchClic ...

Typescript does not directly manipulate values. For instance, using a statement like `if(1==2)` is prohibited

I am currently developing an Angular application with a code coverage report feature. There is a method where I need to skip certain lines based on a false condition. So, I attempted to create a function in my component like this: sum(num1:number,num2:nu ...

Implementing a more efficient method for incorporating UUIDs into loggers

------------system1.ts user.on('dataReceived',function(data){ uniqueId=generateUniqueId(); system2.processData(uniqueId,data); }); ------System2.ts function processData(u ...

Setting up AngularJS 1.5.x to function seamlessly with SystemJS and TypeScript

I'm looking to keep all my code in AngularJS 1.x while also preparing it for an easy upgrade to AngularJS 2 in the future. To align my code with Angular 2 standards, I am interested in using TypeScript and SystemJS in version 1.5.x initially. Is ther ...

Incorrect errors are displayed by VS Code in ts-node shell scripts

I came across an interesting article discussing running a TypeScript file on the command line, and while it seems to be functioning properly, I am encountering invalid errors in VS Code: https://i.sstatic.net/eis3X.png As seen in the terminal (bottom hal ...

Error message thrown by node express.js indicating that response headers cannot be reset once they have been sent

As a newcomer to both node and express, I may be making a silly mistake. If you want to see the complete source code, please visit: https://github.com/wa1gon/aclogGate/tree/master/server logRouter.get("/loggate/v1/listall", function(req, res) { let ...

The inline style in Angular 2 is not functioning as expected when set dynamically

Having a small dilemma... I'm trying to apply an inline style within a div like this: div style="background: url(..{{config.general.image}})"></div Oddly enough, it was functioning in beta 16 but ever since the RC1 upgrade, it's no longer ...

TSLint Alert: Excessive white space detected before 'from' keyword (import-spacing)

I'm currently using WebStorm and working to maintain a specific code style: https://i.sstatic.net/r1n7n.png However, I encounter an issue where TSLint highlights my spacing and provides the following hint: "Too many spaces before 'from' ...

What is the best way to ensure that two promises are both resolved before triggering a function from within a promise?

In my code, I have a forEach loop on a matches fetch that looks like this: matches => { matches.forEach(match => { Promise.all([this.teamService.getTeam(match._links.homeTeam.href)]) .then(team => { match. ...

Tips for integrating Excel files with NestJS

I'm in the process of developing a REST API that will utilize a third-party API to retrieve specific status information. The URLs needed for this API are stored in an Excel file, which is a requirement for this use case. My goal is to extract the URLs ...

Creating TypeScript domain objects from JSON data received from a server within an Angular app

I am facing a common challenge in Angular / Typescript / JavaScript. I have created a simple class with fields and methods: class Rectangle { width: number; height: number; area(): number { return this.width * this.height; } } Next, I have a ...

Obtaining an OBJECT from a hashmap instead of a string

In my code, I am working with a hashmap and I want to extract all the values from this map without needing to reference a specific key. Here is a basic overview of the process: Create a hashmap using an external file with a structure of "id:value" Utili ...

What is the proper way to utilize variables in package.json with npm version 7.x.x?

I am looking to utilize npm scripts to access keys found in the directories section. "directories": { "client": "client", "server": "server" }, "scripts": { "test:client&qu ...