How to dynamically set a value of a specific type using generics in Typescript

canecse

Suppose I have a generic utility class that is supposed to interface with a class and has a method setPropertiesToTrue that takes in a list of class properties, and sets those properties inside the instance of the class to true.

class SomeObject{
  x: boolean 
  y: boolean
  z: string

  constructor(x: boolean,y: boolean,z: string){
    this.x = x,
    this.y = y,
    this.z = z
  } 
}

class ProperySetter<TSomeObject>{
  objectContext: TSomeObject

  constructor(objectContext: TSomeObject){
    this.objectContext = objectContext
  }

  setPropertiesToTrue(properties: Array<keyof TSomeObject>){
    properties.forEach(property => {
      this.objectContext[property] = true
    })
  }
}


const someObject = new SomeObject(false, false, "hello")

const propertySetter = new ProperySetter(someObject);

propertySetter.setPropertiesToTrue(["x", "y"])

console.log(someObject.x) // changed from false to true
console.log(someObject.y) // changed from false to true
console.log(someObject.z) // unchanged


Here is a TS Playground example of more or less what I'm trying to do.

In the example above, (at line 22 in the playground), it appears typescript has no the idea that keys being passed as properties correspond to boolean values inside the generic TSomeObject. So I’m getting the error:

Type 'boolean' is not assignable to type 'TSomeObject[keyof TSomeObject]'.

And this makes sense because keyof TSomeObject correspond to all keys of TSomeObject not just the keys corresponding to the boolean keys.

Is there a way to get around this?

sno2

You can strengthen the constrain of the input array to include only the keys that are boolean values. However, TS is not smart enough to see the know that the keys are valid in the array. Therefore, you're going to just have to go with a cast to get the code to work. Here is an example of the working code with the better constraints on the keys type:

class SomeObject{
  x: boolean 
  y: boolean
  z: string

  constructor(x: boolean, y: boolean, z: string){
    this.x = x,
    this.y = y,
    this.z = z
  } 
}

class ProperySetter<TSomeObject>{
  objectContext: TSomeObject

  constructor(objectContext: TSomeObject){
    this.objectContext = objectContext
  }

  setPropertiesToTrue(properties: Array<keyof { [K in keyof TSomeObject as TSomeObject[K] extends boolean ? K : never]: 0 }>){
    properties.forEach(property => {
      (this.objectContext as any)[property] = true
    })
  }
}


const someObj = new SomeObject(true, true, "hey");
const setter = new ProperySetter(someObj);
setter.setPropertiesToTrue(["x", "y"])

// @ts-expect-error not a boolean property
setter.setPropertiesToTrue(["z"]);

TypeScript Playground Link

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

An array of object with specific type using generics with typescript

How to set type dynamically in typescript using 'es6' style?

Is there a way to coerce a type to dynamically be the same using generics in Typescript?

How to get the data type in Typescript using Generics

How to set a type object as initial value of React using Typescript and useState?

using Java Generics with a specific type

The type to indicate keys that be set specific type value in Typescript

How do I set the parameter for the passed function in typescript using generics?

In TypeScript, how can you extract a class instance type using generics?

How to set typescript type for matchPath return value

How to dynamically set the type of constructor function method in TypeScript

Explicit value type constraints with typescript generics?

How to set type of variable on useState using typescript?

TypeScript - Using Generics to Create a Custom Type

TypeScript cast type using generics and constructor?

Separate type when using generics in TypeScript

How to dynamically set a defined property using a string key TypeScript?

Typescript : how to make type system accurately determine output type based on inputs using <generics>

How to get Type of Array in Typescript generics

How to define a TypeScript type with a variable number of generics

How to overwrite properties of a type with generics in TypeScript?

How to type a function that add a property with generics in typescript?

How to specify using generics/type hints one specific subtype of a type union?

Using a type as a value in typescript

set type dynamically using Createmany

How to dynamically assign a type in typescript

how to dynamically read a specific cell value in a table using selenium and python

Using type families and Generics to find an Id value

How to set an ArrayList Type dynamically using the class name?