首页 > 解决方案 > 基于泛型类型定义 TypeScript 类型

问题描述

让我们data在 TypeScript (4.0.5) 中使用 JSON 类型的列和这个枚举的 SQL 数据库表:

enum EContentType {
  NOTHING,
  IMAGE,
  VIDEO
}

根据ContentType我将不同的 JSON 模式保存data到我的数据库的列中。

例子:

是否可以使用泛型为该data对象创建 TypeScript 类型,该类型将基于什么来正确键入EContentType

像(伪)这样的东西:

type TDataType<ContentType> = {
   [ContentType.IMAGE]: {path: string, type: string}
   [ContentType.VIDEO]: {path: string, length: number}
}

用法:

const concreteType: EContentType = EcontentType.IMAGE;

const typedDataField = dataField as TDataType<concreteType>;

这可能吗?或者不是,因为 TypeScript 只是静态类型的......有什么不同的想法如何保证类型安全(不允许有人length为内容类型保存属性IMAGE)?

如果没有办法做到这一点,那么键入什么会像这样工作:

const data1 = dbDataField as TDataType<EContentType.IMAGE> // {path: string, type: string}
const data2 = dbDataField as TDataType<EContentType.VIDEO> // {path: string, length: number}

标签: javascripttypescript

解决方案


这不起作用,因为您将其声明ContentType为类型但将其用作值。一个更好的方法是使用一个接口和extends你想要的任何你想要预定义的泛型属性

interface TDataType <T>{
   [key: string]: T
}

let a: TDataType<{path: string, type: string}>;
a.IMAGE = {path: 'aaa', type: 'bbbb'};
console.log(a); // output:  "IMAGE": {"path": "aaa", "type": "bbbb"}

或使用Record<Keys, type>实用程序类型来定义https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeystype

interface Content{
  path: string, type: string
}

type ContentType = "IMAGE" | "VIDEO";

const concreteType: Record<ContentType , Content> = {
  IMAGE: { path: "", type: ""}
};

推荐阅读