【问题标题】:Correct typing for generic Database abstraction通用数据库抽象的正确类型
【发布时间】:2020-12-09 16:23:40
【问题描述】:

所以我正在编写一个依赖于 DynamoDB 的后端,作为其中的一部分,我正在节点 SDK 的顶部编写一组简单的函数,以使我的代码更易于测试。在其中一个函数返回数据的情况下,我希望能够将值分配给类型化的对象,而无需返回 any 或不必进行类型转换。我试过这样的通用参数:

export const getAll = async<T extends Record<string, unknown>[]> (
  table: string
): Promise<T> => {
  const params = {
    TableName: table,
  };
  const result = await dynamoDb.scan(params).promise();
  return result.Items ?? [];
};

当我尝试编译它时,我收到以下错误消息

类型“ItemList”不可分配给类型“T”。 'T' 可以用不同的约束子类型 'Record' 来实例化

现在我想我有点明白为什么这不起作用了,因为在编写函数时无法知道 T 是什么,因此无法确保函数实际返回的内容与类型参数。

我尝试将其键入为 record 类型:

type Customer = {
   id: string;
   name: string;
}

export const getAll = async (
  table: string
): Promise<Record<string, unknown>[]>> => {
  const params = {
    TableName: table,
  };
  const result = await dynamoDb.scan(params).promise();
  return result.Items ?? [];
};

但现在当我尝试将其分配给Customer 类型的变量时,我收到以下错误消息:

类型“记录[]”不可分配给类型“客户”:类型“记录”缺少以下类型“客户”的属性:id、名称

目前,我正在做后者,但我必须做一个相当讨厌的as unknown as Customer[] 演员才能让它工作。我确定这是不正确的,所以我非常感谢一些关于如何正确输入的建议。

【问题讨论】:

  • 你对 TS 说你期望 Promise&lt;T&gt; 但同时你试图只返回空数组

标签: typescript


【解决方案1】:

如果您不需要任何运行时类型检查,那么您最好将 DynamoDB 的返回类型转换为 T[],使用如下方式:

import { DynamoDB } from "aws-sdk";
const dynamoDb = new DynamoDB.DocumentClient();

type Customer = {
  id: string;
  name: string;
};

export const getAll = async <T>(table: string): Promise<T[]> => {
  const params = { TableName: table };
  const result = await dynamoDb.scan(params).promise();
  return result.Items as T[] ?? [];
};

const doIt = async () => {
  const customers: Customer[] = await getAll<Customer>("my-customer-id");
  // Do something with your customers
};

【讨论】:

    猜你喜欢
    • 2017-05-02
    • 1970-01-01
    • 2016-09-21
    • 1970-01-01
    • 2019-03-12
    • 2011-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多