I have two interfaces as follows:
interface Foo {
foo: string;
}
interface Bar {
prop1: string;
prop2: string;
}
My goal is to create a type that combines these two interface keys with underline between them, something like this:
type MergeKeys<A,B> = {
[P in keyof A '_' P2 in keyof B]: string;
};
type Result = MergeKeys<Foo,Bar>;
So that the result would be:
interface Result {
foo_prop1: string;
foo_prop2: string;
}
Is this even possible?
CodePudding user response:
Here's one way to do it:
type MergeKeys<A, B> = { [P in
`${Exclude<keyof A, symbol>}_${Exclude<keyof B, symbol>}`
]: string; };
The main idea is to use template literal types to perform the desired string concatenation.
The only wrinkle is that the compiler will reject the simpler `${keyof A}_${keyof B}`
, because TypeScript supports symbol
-valued keys which cannot be serialized to strings via template literals. In order to convince the compiler to serialize keyof A
, we have to get rid of the possibility that any symbol
-valued keys will be in there. That's where the Exclude<T, U>
utility type comes in. The type Exclude<keyof A, symbol>
will return the union of all the keys of A
which are not symbol
s (so you'll get any string
or number
literal types but no symbol
s).
Okay, let's test it:
type Result = MergeKeys<Foo, Bar>;
/* type Result = {
foo_prop1: string;
foo_prop2: string;
} */
Looks good!