I try to create a class with a string contraint but the it gives an error at the get scale() function.
class Scaling<T extends string> {
_scale = "";
constructor(props: T) {
this._scale = props;
}
setScale(scale: T) {
this._scale = scale;
}
get scale(): T {
return this._scale;
}
Type 'string' is not assignable to type 'T'. 'string' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'string'. }
CodePudding user response:
You should remove explicit T
return type from get scale(): T
.
Because during initialization, T
inferes as literal type of argument.
COnsider this 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;
}
}
// T infered as literal "hello"
const result = new Scaling('hello')
Hence, when you want to return T
it should be "hello"
.
In your example, it can't be "hello"
because default value of _scale
is empty string and accordingly it is infered as a string.
let str = ''
// Type 'string' is not assignable to type '"hello"'
const sameCase = (): 'hello' => str
You can't use T
as an explicit type for _scale
because _scale
is mutable and types are immutable.
This is why it is unsafe to return T
type from get scale
Even if i remove the T from the get scale, i still get an error when for const result = new Scaling("hello"); result.setScale("other")
My bad, did not check it.
In order to make this class generic we need to convert infered T
from more specific type to more wider.
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 infered as literal "hello"
const result = new Scaling('hello') // ok
result.setScale('123') // ok
CodePudding user response:
The _scale
member should really be of type T
. For example:
class Scaling<T extends string> {
_scale = "" as T;
constructor(props: T) {
this._scale = props;
}
setScale(scale: T) {
this._scale = scale;
}
get scale(): T {
return this._scale;
}
}
CodePudding user response:
Shouldn't _scale be of type T
? So you'd assign with a colon (:)
class Scaling<T extends string> {
_scale: T;
constructor(props: T) {
this._scale = props;
}
setScale(scale: T) {
this._scale = scale;
}
get scale(): T {
return this._scale;
}
}
The usage would be:
const scaling = new Scaling('Hello World')
console.log(scaling)