Restrictions on pairings of kind variables within generic utilization

Currently, I am creating a declaration file for a library called chart.js. The process of constructing a new chart involves the following:

let chart = new Chart(ctx, { type: 'line', data: ..., options: ... })

The types of the data and options fields are determined by the type field.

To address this, my approach was to define the object's type as a union type. This allows me to specify the acceptable objects that can be passed into the constructor using string literal types for the type field.

However, after construction, the data and options fields become accessible properties from the class. Since I cannot utilize the types of the fields from the passed-in object, I am considering using generics instead.

The current issue is that I would need separate type parameters for each field (type, data, and options), but the specific types of data and options depend on the type specified in the type field. Not all combinations are valid. Is there a method to restrict the possible combinations of type parameters? For example:

let lineChart = new Chart<'line', LineChartData, LineChartOptions> // Valid
let barChart = new Chart<'bar', BarChartData, BarChartOptions> // Valid
let chart = new Chart<'line', BarChartData, LineChartOptions> // Invalid

Answer №1

If I am interpreting your instructions correctly, you can achieve the following:

interface ChartType<Data, Options> {
    type: "line" | "bar";
    data: Data[],
    options: Options[];
}

interface LineType extends ChartType<string, string> {
    type: "line";
}

interface BarType extends ChartType<number, number> {
    type: "bar";
}

class Chart<Data, Options> {
    constructor(ctx: any, type: LineType | BarType) { ... }
}

new Chart("ctx", { type: "line", data: [""], options: [] }); // ok
new Chart("ctx", { type: "bar", data: [98], options: [9] }); // ok
new Chart("ctx", { type: "line", data: [""], options: [3] }); // error
new Chart("ctx", { type: "ha?", data: [], options: [3] }); // error

(code in playground)

Simply substitute my string and number with your specific data/options types.

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

Clear all events from an HTML element and its descendants with TypeScript

Each time the page loads, I have HTML from an API that is constantly changing. Is there a way to strip away all events attached to it? The original HTML looks like this: <div id="content"> <h2 onclick="alert('hi');">Test 1< ...

I am encountering an issue where body-parser is not functioning properly with typescript. Whenever I make a request, the request.body is returning as undefined

Below is the code snippet for my Express application using TypeScript version 3.7.4: import bodyParser from "body-parser"; import config from "config"; import cookieParser from "cookie-parser"; import express from "express"; import mongoose from "mongoose ...

Using the parameter of type 'never' is necessary as per the TypeScript error message, which states that the argument of type 'string' cannot be assigned to it. This error persists even when

const index = selectedActivities.value.indexOf(activity_id); I encountered a TypeScript error saying 'Argument of type 'string' is not assignable to parameter of type 'never'. How can I fix this issue? ...

Is Angular 2 giving you trouble with the AoT compilation and module.id error?

I need to set up AoT compilation for my Angular 2 project. My application is organized into a js directory where all generated .js files are stored, and an app directory containing my .ts, .html, and .css files. For the AoT compilation process, I am usin ...

Issue encountered while accessing theme properties in a ReactJs component with Typescript

I am trying to pass the color of a theme to a component in my TypeScript project (as a beginner). However, I have encountered an error that I am struggling to resolve. The specific error message reads: 'Parameter 'props' implicitly has an ...

What exactly does the use of type assertion as any in Typescript entail?

I'm attempting to dissect a portion of code and figure out its functionality. While I've encountered type assertion before, this particular example is proving to be quite baffling for me. (this.whatever as any).something([]); Here's the la ...

Tips for creating a star program using Angular 2+

Create an Angular 2+ code snippet that will print asterisks (*) in a list on button click. When the button is clicked, it should add one more asterisk to the list each time. For example: Button Click 1 - Output: * Button Click 2 - Output: ** Button Cl ...

Include TypeScript in a single component within an already established Vue project

I've been working on a large Vue project and I want to integrate TypeScript into it. However, every time I try to do so, I run into a lot of errors that take weeks to fix. Instead of going through that, I'd like to find a way to add TypeScript to ...

Tips on verifying the presence of a child in a Firebase list using AngularFire2

I am working on checking the existence of a Firebase list using AngularFire2 in Angular. Below is my parent list: I specifically need to verify if the child element Messages exists within this list. This is the code snippet I have so far: checkChild( ...

What is the best way to conduct tests on Typescript modules that are not intended for

Even though the compiler accepts my current solution without any errors, the tests are still failing with the message "ReferenceError: myFunction is not defined". I am interested in testing the functionality of the following module using TypeScript: File1 ...

How can I make sure that my function returns a mutated object that is an instance of the same class in

export const FilterUndefined = <T extends object>(obj: T): T => { return Object.entries(obj).reduce((acc, [key, value]) => { return value ? { ...acc, [key]: value } : acc; }, {}) as T; }; During a database migration process, I encounte ...

Identify all the CHECKBOX elements that are visible and not concealed

On my page, I have various checkboxes - some with hidden=true and others with hidden=false attributes. Despite trying to use a selector or jQuery to locate checkboxes with the hidden property, I am still facing some challenges. My goal is to differentiate ...

Creating a local HTML file using node.js: A step-by-step guide

Recently, I've delved into developing games using Typescript. However, I've encountered a bit of an issue when attempting to build my game - it requires running on a server. This limitation prevents me from creating an offline game with Node.js a ...

Obtain a reference to a class using a method decorator

My goal is to implement the following syntax: @Controller('/user') class UserController { @Action('/') get() { } } Now in the definition of decorators: function Controller (options) { return function(target: any) { let id ...

What is the process for transforming a string literal type into the keys of a different type?

Imagine having a string literal type like this: type Letters = "a" | "b" | "c" | "d" | "e"; Is there a way to create the following type based on Letters? type LetterFlags = {a: boolean, b: boolean, c: bool ...

Angular release 6: A guide on truncating text by words rather than characters

I'm currently enhancing a truncate pipe in Angular that is supposed to cut off text after 35 words, but instead it's trimming down to 35 characters... Here is the HTML code: <p *ngIf="item.description.length > 0"><span class="body-1 ...

You cannot use objects as valid children in React layout components

I encountered an issue with my layout: Unhandled Runtime Error Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead. The code in my DashboardLayout file (dashboardLa ...

error: encountering issue with Vue TypeScript Jest tests - '$store' property is undefined

I've been facing issues with my tests failing after a recent npm install. I've tried adjusting versions up and down, but haven't had any success. Interestingly, the $store isn't directly used in any of the components or tests. Despit ...

The option value in mat-autocomplete is not displaying correctly on IOS devices

When I click on the first option in the dropdown menu, it does not display the selected option in the field. However, when I select the second option, then the value of the first option appears, and when I choose the third option, the value of the second o ...

Avoid invoking a TypeScript class like a regular function - _classCallCheck prevention

I am currently developing a TypeScript library that needs to be compatible with all versions of JavaScript. I have noticed that when calling a class in TS without using new, it does not compile properly, which is expected. In ES6/Babel, a class automatica ...