Intento crear una clase con una restricción de cadena pero da un error en la función get scale().
class Scaling<T extends string> { _scale = ""; constructor(props: T) { this._scale = props; } setScale(scale: T) { this._scale = scale; } get scale(): T { return this._scale; }El tipo 'cadena' no se puede asignar al tipo 'T'. 'cadena' es asignable a la restricción de tipo 'T', pero 'T' podría instanciarse con un subtipo diferente de restricción 'cadena'. }
Debe eliminar el tipo de retorno T explícito de get scale(): T .
Porque durante la inicialización, T infiere como un tipo literal de argumento. Considere este ejemplo:
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') Por lo tanto, cuando desee devolver T , debe ser "hello" .
En su ejemplo, no puede ser "hello" porque el valor predeterminado de _scale es una cadena vacía y, en consecuencia, se infiere como una cadena.
let str = '' // Type 'string' is not assignable to type '"hello"' const sameCase = (): 'hello' => str No puede usar T como un tipo explícito para _scale porque _scale es mutable y los tipos son inmutables.
Esta es la razón por la que no es seguro devolver el tipo T desde get scale
Incluso si elimino la T de la escala de obtención, sigo recibiendo un error cuando for const result = new Scaling("hello"); resultado.setScale("otro")
Mala mía, no lo comprobé.
Para hacer que esta clase sea genérica, necesitamos convertir la T inferida de un tipo más específico a un tipo más amplio.
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¿No debería ser _scale del tipo T ? Así que asignarías con dos puntos (:)
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; } }El uso sería:
const scaling = new Scaling('Hello World') console.log(scaling)El miembro _scale debería ser realmente del tipo T Por ejemplo:
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; } }