It is advisable to eliminate the explicit T
return type from get scale(): T
.
This is because during initialization, T
is inferred as a literal type of argument.
Consider the following example:
class Scaling<T extends string> {
_scale = "";
constructor(props: T) {
this._scale = props;
}
setScale(scale: T) {
this._scale = scale;
}
get scale(): T {
return this._scale;
}
}
// In this case, T is inferred as the literal "hello"
const result = new Scaling('hello')
Therefore, when you intend to return T
, it should be "hello"
.
In your scenario, it cannot be "hello"
because the default value of _scale
is an empty string and hence it is inferred as a string.
let str = ''
// Type 'string' is not assignable to type '"hello"'
const sameCase = (): 'hello' => str
You cannot designate T
as an explicit type for _scale
since types are immutable and _scale
is mutable.
This is why it is considered unsafe to return the T
type from get scale
Even if I remove the T from the get scale, I still encounter an error when calling const result = new Scaling("hello"); result.setScale("other")
Apologies for the oversight on my part.
To make this class generic, we need to transform the inferred T
from a more specific type to a broader one.
type Infer<T> = T extends infer R ? R : never
class Scaling<T extends string> {
_scale = "";
constructor(props: Infer<T>) {
this._scale = props;
}
setScale(scale: T) {
this._scale = scale;
}
get scale() {
return this._scale;
}
}
// T inferred as the literal "hello"
const result = new Scaling('hello') // ok
result.setScale('123') // ok
Playground