Передать элемент как тип в функции в React / Typescript

#javascript #reactjs #typescript

#javascript #reactjs #typescript

Вопрос:

Я пытаюсь создать общую коллекцию для проекта React в Typescript. У меня есть:

 class List<T>
{
    constructor(data: any){...}
}
 

который создаст список типа. Я хочу привести его к чему-то, вызвав его с помощью чего-то вроде:

 let carList: List<Car> = ...
carList.cast(Car)
 

если предположить, что Car является классом.

Как мне передать тип класса в качестве параметра для его сопоставления? У меня есть это до сих пор:

 public cast(Type: T)
{
    this.list = this.list.map(x => x as Type)
}
 

который не работает, поскольку компилятор жалуется на «Тип ссылается на значение, но используется как тип».
Предположим это.список создается при инициализации списка.

Комментарии:

1. Непонятно, зачем вам нужно что-то подобное. Не могли бы вы объяснить, чего вы пытаетесь достичь?

2. Список предназначался для использования в качестве общего контейнера, который содержал данные вызова базы данных. Затем данные будут проанализированы в список определенного класса. У предыдущей группы, которая работала над проектом, были такие классы, как User, UserList, Submission, SubmissionList и т. Д. Я хотел обобщить их, поскольку казалось, что классы _List были избыточными. Данные API были возвращены с помощью fetch() …затем(apiResponse =>{return new props.responseType(apiResponse)}, где responseType имеет тип {new (data:any): T} .

Ответ №1:

Тип не существует в среде выполнения JS, поэтому вы не можете передать его в качестве параметра функции.

Обычно, чтобы преобразовать ваш список в список во время выполнения, вы должны проверить, возможно ли это. Итак, вам нужно проверить все содержимое списка, и это может быть дорого с точки зрения производительности

 type Guard<T> = (item: any) => item is T;

// https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards

class List<T> {

    constructor(
        public data: T[]
    ) { }

    static getUserGuard<T>(itemGuard: Guard<T>): Guard<List<T>> {
        return (list: List<any>): list is List<T> => list.data.every(itemGuard)
    }
}

// and list usage

const lists: List<any>[] = [
    new List<number>([42]),
    new List<string>(['foo']),
]

const isNumber = (v: any): v is number => typeof v === 'number';
const isString = (v: any): v is string => typeof v === 'string';

// some code with random lists
const doSomething = (lists: List<any>[]) => {
    for (const list of lists) {
        if (List.getUserGuard(isNumber)(list)) {
            // list is List<number> there
        } else if (List.getUserGuard(isString)(list)) {
            // list is List<string> there
        } else {
            // list has some other type there
        }
    }
}
 

Также вы можете проверить мои классы, но не по содержимому

 class List<T> {
    constructor(
        public data: T[]
    ) { }
}

class NumbersList extends List<number> {

}

class StringList extends List<string> {

}

// some code with random lists
const doSomething = (lists: List<any>[]) => {
    for (const list of lists) {
        if (list instanceof  NumbersList) {
            // list is List<number> there
        } else if (list instanceof  StringList) {
            // list is List<string> there
        } else {
            // list has some other type there
        }
    }
}