Using TypeScript: Applying constraints to generic types with primitive datatypes

My TypeScript code includes some generic classes:

type UserId = number
type Primitive = string | number | boolean
class ColumnValue<T, S extends Primitive> {
    constructor(public columnName: String, public value: S) { }
}
abstract class Column<T> {
    constructor(public columnName: String) { }
    public set<S extends Primitive>(value: T): ColumnValue<T, S> {
        return new ColumnValue(this.columnName, this.getValue(value))
    }
    public abstract getValue<S extends Primitive>(value: T): S
}
let id = new class extends Column<UserId> {
    constructor() { super("id") }
    public getValue(value: UserId): number {
        return value
    }
}()

However, I'm encountering an error that reads:

Class '(Anonymous class)' incorrectly extends base class 'Column<number>'.
  Types of property 'getValue' are incompatible.
    Type '(value: number) => number' is not assignable to type '<S extends Primitive>(value: number) => S'.
      Type 'number' is not assignable to type 'S'

Answer №1

When dealing with the getter and setter functions for Columns, it's important to note that the type of S might not always be the same as T. Therefore, it is recommended to move the type parameter to the parent class like this:

Column<T, S extends Primitive>
.

type UserId = number
type Primitive = string | number | boolean
class ColumnValue<T, S extends Primitive> {
    constructor(public columnName: String, public value: S) { }
}
abstract class Column<T, S extends Primitive> {
    constructor(public columnName: String) { }
    public set(value: T): ColumnValue<T, S> {
        return new ColumnValue(this.columnName, this.getValue(value))
    }
    public abstract getValue(value: T): S
}
let id = new class extends Column<UserId, number> {
    constructor() { super("id") }
    public getValue(value: UserId): number {
        return value
    }
}()

The code above runs without errors when tested on the TypeScript playground.https://www.typescriptlang.org/play/#src=...

It's common to want to infer the type S based on the data being used with the setter function. However, the Column class must have a clearly defined type upon instantiation. This means you need to either specify the types explicitly when creating an instance (e.g., new Column<UserId, number>) or include a S parameter in the constructor for easier inference (like in

new Column<UserId>('id', 123)
).

Answer №2

When utilizing your getValue function with a generic type S, it is essential that the inherited implementation also uses the same generic type S.

let id = new class extends Column<UserId> {
    constructor() { super("id") }
    public getValue<S extends Primative>(value: UserId): S {
        return <S>value
    }
}()

By incorporating the generic type S into the class, you have the opportunity to narrow down your function to specifically return a number.

abstract class Column<T, S extends Primative> {
    constructor(public columnName: String) { }
    public set(value: T): ColumnValue<T, S> {
        return new ColumnValue(this.columnName, this.getValue(value))
    }
    public abstract getValue(value: T): S
}

let id = new class extends Column<UserId, UserId> {
    constructor() { super("id") }
    public getValue(value: UserId): number {
        return value
    }
}()

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

Choosing a default selected value from a dropdown list with multiple editing options

When loading my "multiple edit" screen, I default the values as follows: private createFormGroupItem(item: ...): FormGroup { return this.formBuilder.group({ title: new FormControl(item.title, [Validators.required]), effectiveDate: new FormC ...

Modifying a variable within an arrow function does not result in the variable being changed when checked outside of the arrow

I am currently developing an application with Angular and Typescript where I need to update the value of a variable inside a function. To retrieve the data required, I'm utilizing a service. Below is the code snippet for reference: let isDataAvailab ...

Is there a way to extract information from an HttpClient Rest Api through interpolation?

I am currently facing an issue with a component in my project. The component is responsible for fetching data from a REST API using the HttpClient, and the data retrieval seems to be working fine as I can see the data being logged in the Console. However, ...

Error encountered while unit testing a class decorator with type mismatch

I have been tasked with implementing a class decorator that adds an "identify" class method, which returns a class name with the information passed in the decorator. For example : @identifier('example') class Test {} const test = n ...

Issue with Ionic Native File: File.writeFile function - file is not being created and there is no callback response

I've exhausted all the different solutions I could find, but unfortunately, the file isn't getting saved and nothing seems to be happening. The callback functions aren't being called - neither success nor error. Here are the solutions I&apo ...

Implementing Angular 2 - Steps to ensure a service is accessible within the app module

I'm running into an issue trying to utilize a function within a service that I believed was globally accessible. The service in question is named SavedNotificationService: import { Injectable } from '@angular/core'; @Injectable() export cl ...

Bug in timezone calculation on Internet Explorer 11

I've spent hours researching the issue but haven't been able to find any effective workarounds or solutions. In our Angular 7+ application, we are using a timezone interceptor that is defined as follows: import { HttpInterceptor, HttpRequest, H ...

Angular component experiencing difficulty sorting a column sent from parent component to child component

I'm currently facing an obstacle while trying to pass a column from a parent component to a child component in Angular. The issue arises when attempting to sort the column. Below is the code snippet: Parent component <table-sorting-example matSort ...

Exploring the process of selecting checkboxes in Angular 6

I'm currently learning Angular 6 and I have a requirement to mark checkboxes based on specific IDs from two arrays: this.skillArray = [ {ID: 1, name: "Diving"}, {ID: 2, name: "Firefighting"}, {ID: 3, name: "Treatment"}, ...

Reference loss occurs in Angular Ionic when using @ViewChild

This situation is straightforward I am dealing with a reference in this format @ViewChild('myElement') myElementVar : SomeClass; The element I am referencing appears like this <element #myElement *ngIf="someBoolean"></element> As ...

TypeScript version 3.7 has implemented a new feature where it will now display errors for each individual invalid prop instead of grouping them together as it

Scenario using TypeScript 3.5.3 https://i.stack.imgur.com/wykd6.png link to interactive playground - TS 3.5.3 demo running successfully Example with TypeScript 3.7.2 https://i.stack.imgur.com/BPckB.png link to demo - TS 3.7.2 demo not functioning correctl ...

The W3C Validator has found a discrepancy in the index.html file, specifically at the app-root location

While attempting to validate my HTML page, I encountered the following error: Error: Element app-root not allowed as child of element body in this context. (Suppressing further errors from this subtree.) From line 4347, column 7; to line 4347, column 16 ...

The limitation of accessing an object using a key from a callback in Typescript

Whenever I run the code below, I encounter an error message that states Element implicitly have any type because the expression of type string can't be used to index type Chapter. Can someone help me understand what this means? The main goal of this ...

How to Embed HTML Tags in a TypeScript File in Angular

I'm currently utilizing Angular2 and I'm looking to incorporate an HTML tag inside the return function in a TypeScript file. tooltip: (param: any) => { return `<span> ${param.value} </span>`; } I've attempted ...

An error should not be thrown if the object is potentially 'undefined', as there is a filter in place from rxjs

During my service refactoring process, I encountered a frustrating issue. The API I am working with returns an object with various optional properties. To work with these properties, I need to check if they are undefined or not using an if statement, other ...

Typescript enums causing Safari to display blank screen in Next.js

The website performs well on Chrome and Edge, but encounters difficulties on Safari for iOS. Although all the elements, styling, and scripts load properly, nothing appears on the screen. After spending countless hours debugging, I discovered that the pro ...

What could be causing the issue where only one of my videos plays when hovered over using UseRef?

I'm currently working on a project where I have a row of thumbnails that are supposed to play a video when hovered over and stop when the mouse moves out of the thumbnail. However, I've encountered an issue where only the last thumbnail plays its ...

Adjust the dimensions of the ng2-charts to fit your needs

Is there a way to specify the width and height of a chart using ng2-charts? Specifically, I am working on a Bar chart similar to the one shown in the ng2-charts demo. public doughnutChartLabels:string[] = ['EMI', 'Car', 'Food&apos ...

Troubleshooting: NextJS Typescript getInitialProps returning null value

I am currently working with NextJS 'latest' and TypeScript to extract the token from the URL, but I am encountering an issue where it returns undefined. To achieve this, I am utilizing the getInitialProps method. The URL in question looks like th ...

The error message states that the property "user" is not found in the type "Session & Partial<SessionData>"

I recently had a javascript code that I'm now attempting to convert into typescript route.get('/order', async(req,res) => { var sessionData = req.session; if(typeof sessionData.user === 'undefined') { ...