Aller au contenu principal

Exercice 4

Nous vous proposons de typer la fonction selectFields qui, à partir du typage de notre database, sera capable d'inférer les noms des champs qu'il est possible de sélectionner au sein d'une table.

selectFields autocomplete

Rendez-vous dans le fichier 4-selectionner-des-champs.ts et db.ts pour l'implémentation.

À vous de jouer !

Indice 1

Préciser le contexte

Comme précédemment, on peut envisager de construire un type intermédiaire pour préciser la signature du contexte passé selectFields. À ce stade selectFields devra pouvoir être invoqué avec le contexte d'une opération de sélection sur une table membre d'une base de donnée... donnée (any ?).

Indice 2

Le champ des champs possibles

Nous sommes dans un cas similaire à l'exercice précédent, simplement cette fois-ci, on veut pouvoir inférer les types de propriétés nichées un peu plus profondément que les noms des tables.

Suite à l'invocation de selectFrom on dispose, dans notre contexte d'un peu plus d'information : on sait que nous construisons une opération select et surtout quelle table nous allons interroger. Il est alors possible d'extraire, depuis le contexte, les types des clés noms de champs de la table ciblée et ainsi faire en sorte que selectFields n'accepte en second paramètre qu'un tableau dont les éléments sont des membres de champs de la table cible.

Indice 3

La clé des champs

Il est tout à fait possible de définir un lookup type à partir d'un autre lookup type. Notamment ici, nous cherchons à identifier les clés membres d'une table, elle-même membre d'une base de donnée, et ceci afin de spécifier que le second paramètre de selectFields est un tableau dont les éléments sont du type desdites clés.

Indice 4

Oups !

Vous avez peut-être une erreur TypeScript dû à un manque de précision sur le type de l'opération telle qu'elle est retournée par selectFrom (cf. l'exercice précédent). Dans ce cas, il est utile de préciser au compilateur qu'il doit inférer le type le plus précis à partir de la valeur retournée par selectFrom.

Solution

Avant de déplier pour afficher la solution, n'hésitez pas à nous solliciter !
type SelectableContext<DB> = EmptyContext<DB> & {
_operation: "select";
_table: keyof DB;
};
type AnySelectableContext = SelectableContext<any>;
export const selectFields = <Ctx extends AnySelectableContext>(
ctx: Ctx,
fieldNames: (keyof Ctx["$db"][Ctx["_table"]])[]
) => ({
...ctx,
_fields: fieldNames,
});