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.
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});