@OrbiJ

Как правильно ограничивать передаваемые аргументы классов в TypeScript?

Подскажите, пожалуйста, как правильно ограничить тип передаваемых аргументов как производных одного абстрактного класса в методы/функции в typescript?

Конкретная суть: есть абстрактный класс Entity (он полностью пустой) и несколько классов, производных от этого абстрактного класса - User, Book, Film и т.д. Каждый из этих классов представляет собой простенькую модель сущности, которая должна приходить со стороны сервера, вот пример:

class Book extends Entity {

    public id!: bigint;
    public name: string = "";
    public author: string = "";
    public release_date: string = "";
    public about: string = "";
    public image: string = "";


    constructor(id : bigint, name : string, author : string, release_date : string, about : string, image : string | null) 
    {
        super()
        this.id = id;
        this.name = name;
        this.author = author;
        this.release_date = release_date;
        this.about = about;
        this.image = image == null ? Configuration.BOOK_DEFAULT_IMAGE : Configuration.API_BASE_URL + image;
    }


}

export default Book;


Далее я выполняю запрос к апи (например, через axios) и получаю в ответ response с датой, где, по сути, должны быть поля, идентичные наименованиям свойств класса. Для этого я хочу в классе взаимодействия с API завести метод, который будет принимать только потомков абстрактного класса Entity и просматривать перечень их свойств и проверять, чтобы в свойстве data объекта response они не были undefined, но у каждого потомка, понятное дело, свойства свои и мне нужно как-то их просмотреть. И вот на этой стадии я вообще выпал, покопался в этих дженериках для функций (какой-то огрызок templat'ов c++), пробовал просто ограничить тип следующим образом:
public validateRequest (validationModel : Entity) : boolean {
        return true;
    }

И оно, понятное дело, работает, но не совсем так, как мне нужно, ибо требует передачи именно объекта (а мне до момента его создания нужно проверить соответствие свойств), при этом почему-то передача aliasa любых классов вообще не вызывает ошибку, но работает вообще чёрт пойми как, передавая просто сигнатуру класса в виде строки. Смотрел в сторону рефлексии и хотел передавать ссылку на конструктор класса моделей и там проверять, но вообще не понял как это делать, ни в документации, ни на просторах интернета я этой информации не нашёл, не может же такого быть, что её нет в TS? Подскажите, пожалуйста, я вообще правильно думаю или есть какое-то очевидное решение значительно проще?

С дженериками тоже что-то пытался покрутить, но я вообще не выкупил их пригодность для этой задачи, ибо класс в TS вроде как и есть одновременно с этим type, но они вообще разрешали мне пропускать любую информацию в метод, хотя, может, это я просто не понял их...
  • Вопрос задан
  • 132 просмотра
Решения вопроса 1
Aetae
@Aetae Куратор тега TypeScript
Тлен
1. TypeScript работает на этапе компиляции. В рантайме нет никакого тайпскрипта, соответственно и не может быть никаких проверок с ним связанных.
// Есть библиотеки для подобного, но они сильно жирные и слегка "хакнутые", в простых случаях лучше уж руками

2. TypeScript имеет структурную типизацию. Что значит, что учитвает он только структуру. Тип получаемый из пустого абстрактного класса будет принимать в себя абсолютно любой объект. Тип из класса с одним полем "id" примет в себя любой инстанс любого класса с полем "id".
class A { id!: string }
class B { id!: string }
class C { 
 id!: string; 
 value!: number; 
}

const foo: A = new B(); // ok
const bar: A = new C(); // still ok

3. Неизвестный тип в TypeScript обозначается unknown. Функции проверки что неизвестный тип является конкретным называются тайпгарды:
function isString(arg: unknown): arg is string {
  return typeof arg === 'syting'
}

Применяя тайпгарды вы полностью берёте на себя ответственность, что поверки истинны.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы