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
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.