这是我的代码:
type t = 'a' | 'b' | 'c';
const objs = {
obj1: { a: 1 },
obj2: { a: 1, b: 2 },
};
// inferred type is { a: number }
objs.obj1.c; // Error
我想限制
objs
的值具有属于 t
的键。所以我重写如下:
type t = 'a' | 'b' | 'c';
type SubsetOfT = Partial<Record<t, number>>;
const objs: Record<string, SubsetOfT> = {
obj1: { a: 1 },
obj2: { a: 1, b: 2 },
};
// inferred type is {a?: number; b?: number; c?: number}
objs.obj1.c; // number | undefined
然后我就丢失了具体的类型信息。
type t = 'a' | 'b' | 'c';
function constrainKeys<T extends Record<string, Partial<Record<t, number>>>>(obj: T): T {
return obj;
}
const objs = constrainKeys({
obj1: { a: 1 },
obj2: { a: 1, b: 2 }
});
// inferred type is { a: number }, that's good
objs.obj1.c = 1; // Error
这段代码正是我想要的。它可以正确地将 obj1 的值的类型推断为
{a: number;}
而不是 {a?: number; b?: number; c?: number}
。但有没有更简洁的写法呢? constrainKeys
功能会降低可读性。
我认为最后一个例子是正确的。但我没有注意到它根本没有约束密钥。
您可以使用泛型类型:
type t = 'a' | 'b' | 'c';
type ObjectRecord<K extends PropertyKey, T> = Record<string, Partial<Record<K, T>>>;
const objs: ObjectRecord<t, number> ={
obj1: { a: 1 },
obj2: { a: 1, b: 2 }
}
objs.obj1.c = 1;
objs.obj1.d = 1; // Error