The is my code.
type t = 'a' | 'b' | 'c';
const objs = {
obj1: { a: 1 },
obj2: { a: 1, b: 2 },
};
// inferred type is { a: number }
objs.obj1.c; // Error
I want to constrain the value of objs
to have keys belonging to t
. So I rewrite it as below:
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
Then I lost the specific type information.
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
This code is exactly what I want. It can correctly infer the type of the value of obj1 as {a: number;}
instead of {a?: number; b?: number; c?: number}
. But is there a more concise way to write it? The constrainKeys
function reduces readability. I asked GPT, but it couldn’t answer