#typescript #typescript-generics
#typescript #typescript-generics
Вопрос:
Универсальные интерфейсы и классы, они мне нравятся, и я думаю, что они очень полезны. Я только начал их использовать, и я хотел бы понять, почему у меня возникают 2 ошибки, которые у меня есть на игровой площадке TS (ссылка). Я был бы признателен за любую помощь, заранее спасибо.
Проблема 1: возвращаемая переменная o ( Person.fromJson(j)
) реализует IPerson<T,K>
, а T является расширением IPerson<T,K>
, поэтому я не понимаю, почему это неправильно. Я создал базовый вариант использования без общих классов в конце игровой площадки TS, и я не вижу той же ошибки.
Ошибка описания: в возвращаемом o из Person.fromJson(j)
Тип ‘Person<IPerson<неизвестно, JsonPerson>, JsonPerson>’ не может быть присвоен типу ‘T’.
‘T’ может быть создан с произвольным типом, который может быть не связан с ‘Person<IPerson<неизвестно, JsonPerson>, JsonPerson>’
class Person<T extends IPerson<T,K>, K extends JsonPerson> implements IPerson<T,K>{
name: string = "Unknown"
constructor(){}
toJson(): JsonPerson{
return {"name": this.name}
}
fromJson(j: K): T{
let o= new Person()
o.name = j.name
return o
}
}
Проблема 2: ошибка указывает «Тип T не удовлетворяет ….», но если T расширяется IStudent
и IStudent
расширяется IPerson
. Итак, T «расширяет IPerson»? Я думаю, что да (принцип включения). Вот почему я не понимаю следующую ошибку. Возможно, это относится к тому, что оно не удовлетворяет из-за несовместимости с FromJSON, но не уверен, как это решить. Возможно, это связано с проблемой 1.
Ошибка описания: в расширениях Person<T,K>
Тип ‘T’ не удовлетворяет ограничению ‘IPerson<T, K>’. Тип ‘IStudent’ не может быть присвоен типу ‘IPerson<T, K>’. Типы, возвращаемые ‘FromJSON(…)’, несовместимы между этими типами. Тип ‘IStudent’ не может быть присвоен типу ‘T’. ‘IStudent’ может быть присвоен ограничению типа ‘T’, но ‘T’ может быть создан с другим подтипом ограничения ‘IStudent’.
class Student<T extends IStudent, K extends JsonStudent> extends Person<T,K>
implements IStudent{
student: boolean= true
constructor(){
super()
}
toJson():JsonStudent{
return {...super.toJson(), "student":this.student}
}
fromJson(j: K): T{
let o: T = super.fromJson(j)
o.student=j.student
return o
}
}
Ответ №1:
В этом коде много переменных, и его можно было бы немного очистить и упростить.
Суть вашей проблемы заключается в том, что происходит с fromJson
методом, когда вы имеете дело с типом, который более специфичен, чем вы ожидали.
Все учащиеся — это люди, но не все люди являются студентами. Вы сказали, что T extends IPerson<T,K>
и это ключевое extends
слово означает, что T
может включать любые дополнительные свойства. Допустим, вы создаете Person
экземпляр и указываете, что T
для этого экземпляра является вашим ожидаемым объектом person, но также {customProperty: any}
. При вызове fromJson
вы получите Person
объект, который не включает customProperty
в себя, поэтому он не может быть назначен T
.
Вот почему вы получаете ошибки типа "'T' could be instantiated with an arbitrary type which could be unrelated to ___"
и "'T' could be instantiated with a different subtype of constraint ___"
.