I’m looking for a way of replacing keys of a type when it contains the key of another.
I essentially want to do this to map up replacements which I have in another method. We have a large number of objects all in snake case being prettified for display. One of the steps is the replacement of specific keys.
Currently I’m doing:
type Replacements = {
abc: 'cba';
bcd: 'dcb';
};
type Test = {
bcd: string;
aabca: string;
};
type ReplaceKeys<R extends Record<string, string>, T extends Record<string, unknown>> = {
[K in keyof T as K extends keyof R ? R[K] : K]: T[K];
};
type Replaced = ReplaceKeys<Replacements, Test>;
Which gives me this type as expected:
type Replaced = {
dcb: string;
aabca: string;
}
However I’m wondering if there’s a way of replacing keys that are contained. I’ve tried creating a type to do the job:
type ReplaceKeysInferred<
R extends Record<string, string>,
T extends Record<string, unknown>,
> = {
[K in keyof T as K extends `${infer A}${infer RKey extends keyof R & string}${infer B}`
? `${A}${R[RKey]}${B}`
: K]: T[K];
};
type ReplacedInferred = ReplaceKeysInferred<Replacements, Test>;
However the type returned doesn’t contain any replacements:
type ReplacedInferred = {
bcd: string;
aabca: string;
}
Not sure where I’m going wrong.
Edit:
I’ve also tried:
type ReplaceKeysInferred<
R extends Record<string, string>,
T extends Record<string, unknown>,
> = {
[K in keyof T as K extends `${infer A}${infer RKey}${infer B}`
? RKey extends keyof R
? `${A}${R[RKey]}${B}`
: K
: K]: T[K];
};
Which is essentially an extra step on the first type. This works the same as the first type giving back:
type ReplacedInferred = {
bcd: string;
aabca: string;
}
Which still isn’t replacing any contained strings.
1