我看到了你想要的用例GenericType
可以使用任何类型的字符串作为键,但仍然希望在声明它们时准确确定这些键的值是什么。
在这种情况下,您可以使用Record https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeystype类型来限制允许的键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
and key2
具有完整的类型安全性。
Obj1.key1
// (property) key1: {
// prop1: string;
// prop2?: string | undefined;
// prop3?: number | undefined;
// }
EDIT
根据OP的评论,听起来他宁愿不指定所有键名称,或者必须手动检查可选字段是否存在。
我能想到的最好方法是这样做,同时仍然确保您声明的对象与对象的约束相匹配GenericType
接口是做类似下面的事情。
首先你需要这个实用程序类型:
type Constraint<T> = T extends Record<string, {
prop1: string,
prop2?: string,
prop3?: number,
}> ? T : never
这将返回never
if T
不符合约束条件或者只是T
否则。
现在你声明你真正想要的普通对象。没有类型注释。
const CorrectObj = {
key1: {
prop1: "hi",
},
key2: {
prop1: "bye",
prop2: "sup",
},
};
然后将此对象文字分配给另一个变量,但声明新变量的类型必须为Constraint<typeof CorrectObj>
const CheckedObj: Constraint<typeof CorrectObj> = CorrectObj
If 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>
when T
不匹配的是never
,但你仍然试图分配一个非never
价值CheckedBadObj
,导致类型冲突!
这在声明每个对象文字的两个实例时涉及到一些重复,但这是唯一的方法
- 让 TypeScript 知道exactly对象上存在哪些字段,包括所有子对象,同时仍然
- 检查“通用”类型的值
符合你的限制
您可以在操场 https://www.typescriptlang.org/play?#code/C4TwDgpgBAwg9gOwM7AE4EMCWDgB4AqAfFALxT5QQAewECAJklAEoQDGcq9uKq2A5gBooAbwBQUKGFRwwARgBcUXgMESpMsACYA-EpUIh66bIDMeqAgCuAWwBGEVGoC%20xHeShKEEAG6OxARzIwLCcqOzAAPJ2AFakouoA1hAgigmSkibySgBEABaYOWqSzsVQySBaSuIZGrJpOXYgEEXqmZpVUDlIVmCtJS4A3IGIKLB57Mn00TFp8MEY2HigkHAAZqGo4WxRscRk8FsRMyPBUABC6NOx8TXlKWl37XD8a-T82V0F-VClSSmdJ51T6NZo-dr0Nb8WSdbq9H5-ZzDMRBMYwCZsKaXa4xJTzXhYHC4FYQdYXK4zfbknFAA.