I am facing an issue with a data object that stores values and their previous values. The keys for the previous values are suffixed with ":previous" e.g. foo
and foo:previous
. However, I encountered a type error when trying to assign values to the previous values, stating
Type "foo" is not assignable to type "${K}:previous"
. It seems that TypeScript does not recognize that both types have the same structure. I attempted to resolve this by:
type PostfixKeys<T> = {
[K in keyof T as `${string & K}:previous`]: T[K];
}
type Foo2 = Foo & PostfixKeys<Foo>
type Foo = { "foo": string; "bar": boolean }
const test = <K extends keyof Foo>(key: K, foo: Foo2) => {
foo[`${key}:previous`] = foo[key]; // <= Type '"foo"' is not assignable to type '`${K}:previous`'.(2322)
}
What would be the most effective way to resolve this issue? Here is a Playground with this code.
I attempted using T[keyof T]
instead of T[K]
which resolved the typing issue. However, TypeScript did not correctly infer the value associated with the key in relation to the ":previous
" suffix:
type PostfixKeys<T> = {
[K in keyof T as `${string & K}:previous`]: T[keyof T];
}
type Foo2 = Foo & PostfixKeys<Foo>
type Foo = { "foo": string; "bar": boolean }
const test = <K extends keyof Foo>(key: K, foo: Foo2) => {
foo[`${key}:previous`] = foo[key]; // <= works but
const bat = foo["bar:previous"]; // <= is not type `string | boolean` instead of `boolean` as it was correctly when using T[K]
}
This approach also compromises type safety, making it unsuitable for my requirements.