我有一个通用类型
type GenericType = {
[key: string]: {
prop1: string,
prop2?: string,
prop3?: number,
},
};
我使用通用类型来帮助构建/类型检查我创建的新对象。
const Obj1: GenericType = {
key1: {
prop1: "hi",
},
key2: {
prop1: "bye",
prop2: "sup",
},
};
有效。但是,当我使用新对象时,vscode / typescript在不删除Obj1
的情况下不会显示GenericType
的键或道具。我也可以“扩展”类型,但这就是代码重复。
Obj1.???
是否可以在通过我从它创建的新对象访问更特定的道具的同时保留GenericType?
更新1
我希望vscode /打字稿能够显示/验证
Obj1.key1.prop1
Obj1.key2.prop1
,如果出现错误,则
Obj1.key1.prop2
Obj1.key2.prop3
Obj1.key2.prop321
答案 0 :(得分:1)
我看到这种情况的用例是,您希望GenericType
拥有任何类型的字符串作为键,但仍想确定在声明它们时这些键的值可以是什么。
在这种情况下,您可以利用Record
类型将Obj1
的允许键限制为仅您指定的键。
type GenericType<K extends string> = Record<K, {
prop1: string,
prop2?: string,
prop3?: number,
}>
然后,在定义Obj1
时,可以通过将允许键的并集设置为第一类型参数来指定允许键的类型。
const Obj1: GenericType<"key1" | "key2"> = {
key1: {
prop1: "hi",
},
key2: {
prop1: "bye",
prop2: "sup",
},
};
TypeScript现在可让您以完全类型安全的方式访问key1
和key2
。
Obj1.key1
// (property) key1: {
// prop1: string;
// prop2?: string | undefined;
// prop3?: number | undefined;
// }
编辑
根据OP的评论,听起来他宁愿不指定所有键名,也不必手动检查可选字段的存在。
我想做到这一点,同时又确保所声明的对象与GenericType
接口的约束匹配的最好方法是执行以下操作。
首先,您需要以下实用程序类型:
type Constraint<T> = T extends Record<string, {
prop1: string,
prop2?: string,
prop3?: number,
}> ? T : never
如果never
与约束不匹配,则返回T
,否则返回T
。
现在,您声明实际需要的普通对象。没有类型注释。
const CorrectObj = {
key1: {
prop1: "hi",
},
key2: {
prop1: "bye",
prop2: "sup",
},
};
然后,您将此对象常量分配给另一个变量,但声明新变量的类型必须为Constraint<typeof CorrectObj>
const CheckedObj: Constraint<typeof CorrectObj> = CorrectObj
如果CorrectObj
符合约束条件,则CheckedObj
将是CorrectObj
的简单副本,其中所有字段都可用。
如果对象文字不符合约束条件,但是在尝试将CheckedBadObj分配给文字时会出现类型错误:
const BadObj = {
key1: {
progfdgp1: "hi",
},
key2: {
prop1: "bye",
prdfgop2: "sup",
},
};
const CheckedBadObj: Constraint<typeof BadObj> = BadObj
// ^^^^^^^^^^^^^
// Type '{ key1: { progfdgp1: string; }; key2: { prop1: string; prdfgop2: string; }; }' is not assignable to type 'never'. (2322)
解释是Constraint<T>
不匹配时T
为never
,但是您仍在尝试为{{1}分配非never
值},导致类型冲突!
这在声明每个对象文字的两个实例时涉及一些重复,但这是唯一的方法
您可以在playground中使用这种方法。
答案 1 :(得分:1)
假设您的目标是在key1
的自动完成菜单中显示key2
和Obj1
,但是稍后仍然可以设置其他键,这是一个可能的解决方案:
type GenericType = {
[key: string]: {
prop1: string,
prop2?: string,
prop3?: number,
};
};
const generify = <T extends GenericType>(obj: T): T & GenericType => obj;
const Obj1 = generify({
key1: {
prop1: "hi",
},
key2: {
prop1: "bye",
prop2: "sup",
},
});
我现在无法想到一个更简单的解决方案,该解决方案将使Obj1
与仅包含GenericType
和key1
属性的特定类型之间具有相同的交集类型。
答案 2 :(得分:0)
使用通用实用程序功能( * @ORM\Entity(repositoryClass=UserRepository::class)
* @ORM\Table(name="difc_user")
* @AttributeOverrides({
* @AttributeOverride(name="password",
* column=@ORM\Column(
* nullable=true
* )
* ),
* }
* )
*
* @UniqueEntity("email")
)
enforce
)确保对象与GenericType
匹配代码:
extends
type GenericType = {
[key: string]: {
prop1: string,
prop2?: string,
prop3?: number,
};
};
const enforce = <T extends GenericType>(obj: T): T => obj;