Home > Blockchain >  Can I prevent typescript from defining a generic as a literal number
Can I prevent typescript from defining a generic as a literal number

Time:01-05

I am trying to create a class that takes both number (for hex) and a number[] (for rgb) as a color option and to also be referenced in a getter/setter. Currently the array works fine, however when using hex values it forces the generic to be a literal number, for example 0xff00ff is being defined as 16711935 instead of number.

This creates an issue where it cannot be redefined, as setting color to 0xff0000 created the following TS error

Type '16711680' is not assignable to type '16711935'

A code example can be found on this playground

I have forced the cast to the class, and it solves the issue (new MyClass<number>({...})). However if there is a way to prevent forced literals automatically, that would be preferable against having to make the user cast the type directly during the class instantiation

CodePudding user response:

The first option that comes to my mind would be to store the whole MyClassOptions as T and not just the type of color.

class MyClass<T extends MyClassOptions<ColorLike>> {
    static readonly DEFAULT_OPTIONS: MyClassOptions<number> = { color: 0x000000 };

    private _realColor!: T["color"];

    constructor(options: T) {
        options = { ...MyClass.DEFAULT_OPTIONS as T, ...options };
    }

    get color(): T["color"] { return this._realColor; }
    set color(value: T["color"]) { this._realColor = value; }
}

const a = new MyClass({ color: [1, 0, 1] });
//    ^? const a: MyClass<{ color: number[]; }>
a.color = [1, 0, 0]

const b = new MyClass({ color: 0xff00ff });
//    ^? const b: MyClass<{ color: number; }>
b.color = 0xff0000 

Since the supplied value of color is nested inside the generic type, TypeScript will not infer the literal type.


Playground

CodePudding user response:

The problem is that you are submitting an object without defining type in it's content, so it become "immutable" if you will.

For example, if you specify a type of the color in that object it will work fine:

const b = new MyClass({ color: 0xff00ff as number});
  • Related