Can a Typescript class type be defined without explicitly creating a JavaScript class?

I am exploring the idea of creating a specific class type for classes that possess certain properties. For example:

class Cat {
  name = 'cat';
}

class Dog {
  name = 'dog';
}

type Animal = ???;

function foo(AnimalClass: Animal) {
  console.log((new AnimalClass()).name);
}

I am looking to have doSomething be able to accept any class that includes a string property named name. The approach I have taken so far involves:

class _Animal {
  name: string;
}

type Animal = typeof _Animal;

I am wondering if there is a way to achieve this without having to define a new JavaScript class and simply focus on specifying the type.

Answer №1

One way to explain a constructor is by using the new expression:

type AnimalContructor = new () => { name: string };

function foo(AnimalClass: AnimalContructor) {
  console.log((new AnimalClass()).name);
}

Interactive example here


Another approach is creating a union of constructors:

type AnimalContructor = typeof Cat | typeof Dog;

Test it out here

Answer №2

To handle this scenario, you can utilize generics. Define a type that is only allowed to be assigned to an object with a name property as a string. Then, introduce a generic type that extends the Animal type. This approach eliminates the need to create a new class for Animal.

class Cat {
  name = "cat";
  age = 2;
}

class Dog {
  name = 'dog';
}

class Car {
  brand = "Audi";
}

type Animal = {name: string};

function doSomething<T extends Animal>(animal: T) {
}

doSomething(new Dog());
doSomething(new Cat());
doSomething(new Car()); // TypeScript error - car is missing name

If you want to extend the Animal type with another class, you can use intersection

class Cat {
  name = "cat";
  age = 2;
}

class Information {
  year = 2020;
}
class Dog extends Information {
  name = 'dog';
}

type Animal = { name: string } & Information;

function doSomething<T extends Animal>(animal: T) {
}

doSomething(new Dog());
doSomething(new Cat()); // TypeScript error - cat is missing year

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 functionality of PHP in relation to the jQuery post feature seems to be malfunction

After developing the JavaScript functionality for this contact form, below is the HTML structure without any CSS styling included: <!-- Contact Form --> <div class="cws-widget"> <div class="widget-title" style="color:#fec20b;">S ...

Go back to the pop-up window if an error occurs

I've implemented a modal window in front of my index page. When the model is valid, I redirect to the index view. However, when the model is not valid, I want it to stay on the modal. How can I achieve this? [HttpPost] [ValidateAntiForgeryToken] publ ...

The issue arises when React child props fail to update after a change in the parent state

Here's the main issue I'm encountering: I am opening a websocket and need to read a sessionId from the first incoming message in order to use it for subsequent messages. This should only happen once. I have a child component called "processMess ...

What could be the issue with my interactive dropdown menu?

I am currently experiencing an issue with a drop down list that is supposed to fetch records from a column in another table, but no records are appearing. Additionally, I would like to add an option in the drop down list labeled "others" for users to inp ...

Retrieve the data stored in a selection of checkbox fields on a form

I have a table of checkboxes: <div> <h1 class="text-center">Select activities</h1> <div class="row"> <div class="col"></div> <div class="col-md-8 col-lg-8"> <h3>Link activ ...

Troubleshooting issue with Bootstrap's responsive scrollspy functionality

I am experiencing an issue with the responsiveness of my page. When I reduce the width of the page to half, the scrollspy disappears unexpectedly. I am unsure about the root cause of this problem. If you run the code I have shared here, you can observe th ...

Determining the data type of a generic variable within an Angular component

I'm currently in the process of developing a versatile component that can handle data of only two specific types: interface X{ name: string, path: string, type: string, } interface Y{ name: string, path: string, } Both types X a ...

Bring in properties from a separate file in Vue3

Currently, I am utilizing Vue3 along with the options API. Within my setup, there are various Vue components that rely on a shared prop defined as: exercise: { type: Object as PropType<Exercise>, required: true, }, To streamline this pro ...

Ways to retrieve the ID attribute value of the third ancestor above

How can I retrieve the ID attribute of the 3rd parent element when a link is clicked? Take for example: <div id="First Div"> <div class="class A"> <div class="class B"></div> <div class="class C"></div> &l ...

Another option instead of using useCallback

Forgive me if this is a novice inquiry, but I am still learning JavaScript and React. I recently discovered the necessity of utilizing useCallback to wrap callback functions in order to prevent them from being recreated constantly when used within a fun ...

Creating tube-like geometry in intervals using three.js

Is there a way in Tube Geometry(Three.js) to plot and render only a portion of the tube at a time, with the option to continue plotting from that point after a set interval or timer? ...

Display all elements on a webpage using Javascript without the need for scrolling

I'm looking for a way to ensure all items on a webpage load immediately, without having to scroll down multiple times before running a script to find a specific item. Is there a method to have all items load at once without the need to manually scroll ...

Finding out which side of a cube has been clicked---Let's identify the side

Currently, I am in the process of developing a navigation menu and I am looking for a way to detect which side the user has clicked. Is it possible to achieve this using raycasting or is there an alternative method that would work better? If you require i ...

Prevent secret select fields from being submitted within a form

In my interface, there are a couple of dropdowns where a user can select the first option and based on that selection, a new dropdown will appear. Currently, when posting the form, all the select dropdown values are included in the post data, even the hid ...

I'm curious about the Next.js type that corresponds to the Redirect object

It's possible to set up redirection in Next.js by configuring it like this: module.exports = { async redirects() { return [ { source: '/about', destination: '/', permanent: true, }, ] ...

Using AngularJS and ServiceStack webservice, perform the "get('url')" operation

I'm completely new to AngularJS and I'm attempting to retrieve some JSON items from a webservice I quickly set up using ServiceStack. When I enter the URL in the browser, I can see the JSON object without any issues. However, for some reason Angu ...

Is it feasible to incorporate a multi-level navigation menu into the "NavItem" component using MaterialUI with TypeScript?

Instructions for creating a multi-level navigation menu using MaterialUI and TypeScript: To the existing '/questions' section, it is desired to include the following 2 navigation menus: /questions/Tags /questions/Users This should resemble the ...

Creating vibrant squares using HTML and CSS

My objective is to incorporate 3 input options for selecting the color, size, and amount of cubes. The image below showcases my peer's final project, but unfortunately, he refused to share the code with me. We were given a basic template to begin with ...

How come props do not get updated along with state changes?

I've encountered an issue where the state of a component being passed into another component as a prop is not updating correspondingly. Various attempts have been made to resolve this, including placing it in the return function and updating the "low ...

Angular: Understanding the intricacies of HTTP calls in ngOnInit versus click events (potentially related to caching mechanisms)

Within my Angular application, I have a basic service configured to communicate with the server. The service has been injected into a component. Interestingly, when I directly call one of its methods inside the ngOnInit() method of the component, everythin ...