如何解决如何从使用[key:string]实现接口的对象的属性中获取联合类型?
我有这个interface
,用于定义PRODUCT_CATEGORIES
对象,在其中我为应用程序中的所有可用产品类别保留了“真相来源”。每个类别都是一个字符串,每个字符串必须具有语言属性EN | ES
和每种语言的label
属性。
interface PRODUCT_CATEGORIES_TYPE {
[key: string]: {
[key in LANGUAGE]: {
label: string
}
}
}
这是我初始化PRODUCT_CATEGORIES
CATEGORIES.ts
export const PRODUCT_CATEGORIES: PRODUCT_CATEGORIES_TYPE = {
category1: {
EN: { label: "Label english" },ES: { label: "Label spanish" },},category2: {
EN: { label: "Label english" },// AND SO ON...
};
我想要一种方法来获取那些在PRODUCT_CATEGORIES
中初始化为联合(即category1 | category2
)的类别键,以便可以在我的PRODUCT
界面中使用。
EX:
interface PRODUCT {
category: "category1" | "category2"
}
但是我需要基于PRODUCT_CATEGORIES
中初始化的类别来动态地实现。
我已经尝试过了,但是不起作用:
interface PRODUCT {
category: keyof typeof import("../constants/CATEGORIES").PRODUCT_CATEGORIES,}
那只是category: string | number
而不是"category1" | "category2"
额外的想法
我还可以为该联合定义一个新类型,但是感觉就像在复制我的JS运行时代码中已经存在的声明。喜欢:
这是正常现象还是不好的做法?我的意思是,类别将在PRODUCT_CATEGORIES
对象中定义,因此这是我的应用中这些值的真实来源。为什么我需要将它们“预先声明”到类型文件中?
type CATEGORY_VALUES = "category1" | "category2"
// THEN I COULD DO
type PRODUCT_CATEGORIES_TYPE {
[key in CATEGORY_VALUES]: {
[key in LANGUAGE]: {
label: string
}
}
}
interface PRODUCT {
category: BLOGPOST_CATEGORY_VALUES
}
解决方法
我建议添加一个助手:
function defineProductCategories<T extends PRODUCT_CATEGORIES_TYPE>(data: T): T {
return data
}
现在,使用它:
export const PRODUCT_CATEGORIES = defineProductCategories({
category1: {
EN: { label: "Label english" },ES: { label: "Label spanish" },},category2: {
EN: { label: "Label english" },// AND SO ON...
});
然后可以推断PRODUCT_CATEGORIES
的键:
interface PRODUCT {
category: keyof typeof PRODUCT_CATEGORIES // "category1" | "category2"
}
说明
此说明:
export const PRODUCT_CATEGORIES: PRODUCT_CATEGORIES_TYPE = { ... }
…几乎等同于:
export let PRODUCT_CATEGORIES: PRODUCT_CATEGORIES_TYPE;
PRODUCT_CATEGORIES = { ... };
…PRODUCT_CATEGORIES
的类型为PRODUCT_CATEGORIES_TYPE
,它是键/值字典。
如果要将密钥保留为PRODUCT_CATEGORIES
类型,则必须保留原始的推断类型:
export const PRODUCT_CATEGORIES = { ... };
有效。但是随后您仍然需要检查PRODUCT_CATEGORIES
的类型。 defineProductCategories
的作用是在执行检查时保留原始类型。
是否干燥?
我还可以为该联合定义一个新类型,但是感觉就像在复制我的JS运行时代码中已经存在的声明。
这是见仁见智。但一种方法是问:合同在哪里?您可以在此处确定CATEGORY_VALUES
是合同:
type CATEGORY_VALUES = "category1" | "category2"
…然后PRODUCT_CATEGORIES
是一个实现。
但是您可以将PRODUCT_CATEGORIES
是作为所有应用程序的常量。然后可以推断出CATEGORY_VALUES
:
type CATEGORY_VALUES = keyof typeof PRODUCT_CATEGORIES;
...,代码为DRY。
两个版本均有效。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。