Типскрипт: Предоставление универсального типа, массив против кортежа, для данных базы данных

0

Вопрос

Я использую библиотеку mssql, в которой есть это interface:

export interface IRecordSet<T> extends Array<T> {
    columns: IColumnMetadata;
    toTable(name?: string): Table;
}

У меня есть функция, которая получает данные из базы данных и возвращает массив IRecordSet<T>, так что это массив массивов, которые содержат универсальный тип <T>. Это выглядит так:

[[{}, {}, ...], [{}, {}, ...], ...]

import { IRecordSet } from 'mssql'

type Data<T> = Array<IRecordSet<T>>

async function getData (sql: string): Promise<Data<any>> {
  // connect to db, run sql
  return []
}

Теперь мне нужна функция, которая вызывает getData(), и я хотел бы ввести фактические возвращенные данные, указав общий тип в IRecordSet<T>.

Я знаю, что это не работает, но это то, что у меня есть прямо сейчас:

interface BookData {
  name: string
  author: string
}
interface CarData {
  make: string
  model: string
}

type BooksAndCars = Data<[BookData, CarData]>

async function getBooksAndCars (): Promise<void> {
  const myData: BooksAndCars = await getData(`
    SELECT name, author FROM Books;
    SELECT make, model FROM Cars;
  `)

  const firstBook: BookData = myData[0][0]
  const cars: CarData[] = myData[1]

  // ...
}

Машинописный текст говорит:

  • Type '[BookData, CarData]' is not assignable to type 'BookData'.
  • Type 'IRecordSet<[BookData, CarData]>' is not assignable to type 'CarData[]'.

Я понимаю эти ошибки, но я не знаю, как ввести myData, firstBook & cars переменные, использующие определенные интерфейсы (BookData & CarData).

Что должно type BooksAndCars = Data<[BookData, CarData]> быть...?

types typescript
2021-11-23 19:20:57
1

Лучший ответ

1

Похоже, ты хочешь BooksAndCars быть кортежем ровно из двух элементов разных типов:

type BooksAndCars = [IRecordSet<BookData>, IRecordSet<CarData>];

Но в getData() функция возвращает Promise<Data<any>>, или, что эквивалентно, a Promise<Array<IRecordSet<any>>>. И, к сожалению, для вашего варианта использования это означает myData будет иметь тип Array<IRecordSet<any>>, массив неизвестной длины, в котором первый и второй элементы имеют неразличимые типы. В TypeScript считается ошибкой типа присвоение такого однородного массива неизвестной длины двухэлементному гетерогенному кортежу, поскольку компилятор не может гарантировать, что возвращаемый массив содержит ровно два элемента правильного типа в правильном порядке.

Если вы уверены, что то, что вы делаете, безопасно, и хотите отказаться от проверки типа компилятором, вы можете использовать утверждение типа, чтобы просто сказать компилятору, чтобы он не беспокоился об этом:

async function getBooksAndCars(): Promise<void> {
  const myData = await getData(`
    SELECT name, author FROM Books;
    SELECT make, model FROM Cars;
  `) as BooksAndCars

  const firstBook = myData[0][0];
  const cars: CarData[] = myData[1]

  // ...
}

Я думаю, что утверждение типа, вероятно, является правильным решением здесь, потому что getData()тип возвращаемого значения включает в себя any введите, значит, вы уже отказались от гарантий безопасности типа. Не намного хуже предположить, что вы возвращаете кортеж, чем предположить, что вы возвращаете массив BookData | CarData. В любом случае вы должны быть осторожны, чтобы ваш sql-запрос действительно возвращал данные ожидаемой длины и типов.

Если бы вы действительно заботились о безопасности типов, вы бы написали код времени выполнения для проверки длины и типов, а затем мы могли бы поговорить о том, как заставить компилятор распознать, что ваши проверки должны сузиться с Promise<Data<object>> (или что-то в этом роде), чтобы BooksAndCars. Но я не буду здесь идти по этому пути, так как это выходит за рамки заданного вопроса.

Ссылка на игровую площадку для кода

2021-11-24 20:25:18

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................

Популярное в этой категории

Популярные вопросы в этой категории