Возвращает расширение универсального интерфейса

#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 ___" .