Полученная ошибка выглядит примерно так:
Type '{ name: string }' is not assignable to type 'Readonly<S>'.
Это говорит о том, что если у вас есть переменная типа Readonly<S>
, тогда присваивать значение типа * 1005 небезопаснок этому.Давайте посмотрим, почему.
Поскольку S
является общим, код, который вы пишете с ним, должен быть совместим с заменой любого действительного конкретного типа для S
.Ограничение на S
равно S extends ParentState
, поэтому давайте придумаем тип, который соответствует этому ограничению, и создадим для него Parent
:
interface ProblemChildState extends ParentState {
naughtiness: true
}
const problemComponent = new Parent<{}, ProblemChildState>({});
Давайте представим, что делает этот конструктор, теперь, когда S
был конкретно указан как ProblemChildState
:
this.state = { name: '' }; // oops!
Тип this.state
равен Readonly<ProblemChildState>
, но, как вы можете видеть, значение { name: '' }
не является действительным ProblemChildState
ввсе, поскольку отсутствует свойство naughtiness
.
Поскольку это назначение недопустимо для конкретного ProblemChildState
, назначение должно быть недействительным для универсального S
.Отсюда и ошибка.
На практике трудно присвоить литеральное значение переменной общего типа.Даже в тех редких случаях, когда вы можете придумать что-то, что работает для всех возможных реализаций параметра универсального типа, компилятор, скорее всего, выдаст вам ошибку, потому что ситуация слишком редкая, чтобы ее можно было проверить, и вам потребуетсясделать утверждение типа .Действительно, вы можете обойти эту проблему, выполнив такое утверждение:
this.state = { name: '' } as Readonly<S>; // not safe!
, но это небезопасно по причине, указанной выше.В идеале вы должны изменить свой код, чтобы он не требовал установки state
, пока у вас не будет конкретного типа для S
.Возможно, сделав Parent
abstract
класс?
В любом случае, надеюсь, это поможет.Удачи!