Tapuscrit: Fourniture de type générique, array vs n-uplet, pour les données de base de données

0

La question

Je suis à l'aide de la mssql bibliothèque qui a cette interface:

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

J'ai une fonction qui récupère les données d'une base de données et renvoie un tableau de IRecordSet<T>, de sorte que c'est un tableau de tableaux qui contiennent le type générique <T>. Cela ressemble à:

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

import { IRecordSet } from 'mssql'

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

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

Maintenant, j'ai besoin d'une fonction qui appelle getData()et j'aimerais le type réel de données retourné en fournissant le type générique dans IRecordSet<T>.

Je sais que cela ne fonctionne pas, mais c'est ce que j'ai en ce moment:

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]

  // ...
}

Tapuscrit est en disant:

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

Je comprends que ces erreurs, mais je ne sais pas comment le type le myData, firstBook & cars des variables en utilisant les interfaces définies (BookData & CarData).

Ce qui devrait type BooksAndCars = Data<[BookData, CarData]> être..?

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

La meilleure réponse

1

Il semble que vous souhaitez BooksAndCars un n-uplet d'exactement deux éléments de types différents:

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

Mais l' getData() la fonction retourne un Promise<Data<any>>ou , de manière équivalente un Promise<Array<IRecordSet<any>>>. Et malheureusement pour votre cas d'utilisation, cela signifie que myData sera de type Array<IRecordSet<any>>, un tableau de longueur inconnue, où les premier et deuxième éléments de distinguer les types. Il est considéré comme une erreur de type dans le fichier d'enregistrement pour vous attribuer un tel inconnu-longueur homogène tableau à deux éléments hétérogènes tuple, car le compilateur ne peut pas garantir que le tableau retourné a exactement deux éléments du droit type dans le bon ordre.

Si vous êtes sûr que ce que vous faites est sûr, et que vous voulez renoncer à la vérification de type par le compilateur, vous pouvez utiliser une assertion de type juste de lui dire que le compilateur ne vous inquiétez pas à ce sujet:

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]

  // ...
}

Je pense qu'un type d'assertion est probablement la voie à suivre ici parce que getData()le retour de type implique l' any type si vous avez déjà donné sur le type de garanties de sécurité. Il n'est pas bien pire à supposer que vous obtenez de retour d'un n-uplet qu'il est à supposer que vous êtes obtenir un tableau de BookData | CarData. Vous devez être prudent de toute façon que votre requête sql vraiment renverra les données de la longueur et les types que vous attendez.

Si vous n'avez vraiment se soucier de la sécurité de type, vous devez écrire exécution de code pour vérifier la longueur et les types, et nous pourrions alors parler de la façon de faire le compilateur reconnaître que votre contrôle étroit de Promise<Data<object>> (ou quelque chose) à BooksAndCars. Mais je ne vais pas aller dans cette voie ici, car il est hors de la portée de la question posée.

Aire de jeux lien vers le code

2021-11-24 20:25:18

Dans d'autres langues

Cette page est dans d'autres langues

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................