让我们在TypeScript(4.0.5(:中创建一个SQL数据库表,其中列data
为JSON类型
enum EContentType {
NOTHING,
IMAGE,
VIDEO
}
根据ContentType
,我将不同的JSON模式保存到数据库的data
列中。
示例:
- 对于
IMAGE
,保存{"path": "/foo/bar", "type": "jpeg"}
- 对于
VIDEO
,保存{"path": "/foo/bar", "length": 60}
是否可以使用基于EContentType
正确键入的泛型为该data
对象创建TypeScript类型?
类似(伪(:
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只是静态类型的。。。如何保证类型安全(不允许有人为IMAGE
内容类型保存length
属性(?
如果没有办法做到这一点,那么键入什么会像这样工作:
const data1 = dbDataField as TDataType<EContentType.IMAGE> // {path: string, type: string}
const data2 = dbDataField as TDataType<EContentType.VIDEO> // {path: string, length: number}
这将不起作用,因为您将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: ""}
};
type TDataType = {
[key in EContentType]: {path: string, type: string}
}
type TDataType2<T> = {
[key in keyof T]: { path: string; type: string };
};
你可以这样使用。
示例(
enum EContentEnum {
NOTHING,
IMAGE,
VIDEO,
}
type TDataType2<T> = {
[key in keyof T]: { path: string; type: string };
};
const contentData: Pick<TDataType2<typeof EContentEnum>, 'IMAGE'> = {
IMAGE: {
path: 'imagePath',
type: 'imageType',
},
};
contentData.IMAGE
这是我的答案,但我不确定你是否想要。
有点晚了,但这里有一个可能的解决方案:
enum EContentType {
NOTHING,
IMAGE,
VIDEO,
}
type TBaseDataType = {
path: string;
};
interface IImageType extends TBaseDataType{
type: string;
}
interface IVideoType extends TBaseDataType {
length: number;
}
type TDataType<T extends EContentType = EContentType.IMAGE> = T extends EContentType.IMAGE ? IImageType : IVideoType;
const image: TDataType<EContentType.IMAGE>;
这只是一个例子,但它允许您使用相同的类型并动态选择所需的图像或视频类型。