type-fest
type-fest copied to clipboard
Merge doesn't is not that useful with indexed types
When using Merge with an indexed type on either left or right hand all the well-known properties are lost. This is because keyof of an indexed type always returns 'string | number', because every key is possible in that object.
Example:
type Example = {
foo: string,
bar: symbol,
[key: string]: unknown,
}
type Foo = {
bar: Date,
}
/*
We would expect something like:
{
foo: string,
bar: Date,
[key: string]: unknown,
}
but it actually returns:
{
[key: string]: unknown,
[key: number]: unknown,
}
*/
type result = Merge<Example, Foo>
This is a well-known caveat with Typescript that was discussed in a few issues (https://github.com/microsoft/TypeScript/issues/45367, https://github.com/microsoft/TypeScript/issues/31153), the behavior is actually intended.
And Omit indeed loses the well-known keys in the same way:
/*
Returns:
{
[key: string]: unknown,
[key: number]: unknown,
}
*/
type omit = Omit<Example, 'foo'>
/*
Our current implementation of Except on the other hand works fine with indexed types
This returns:
{
bar: Date,
[key: string]: unknown,
}
*/
type except = Except<Example, 'foo'>
What I propose is to either change Merge to support indexed types and return what I'm expecting on the example (similar to except), which could be a breaking change for people expecting to lose typing on these cases (but I doubt is a useful behavior), or we can create a new MergeWellKnownKeys that treats indexed types. What do you guys think?
I can work on a PR as soon as we decide on an implementation. It should be easy because we already have an internal type doing the same thing on our company's project
What I propose is to either change Merge to support indexed types and return what I'm expecting on the example (similar to except)
I agree. That's the expected behavior. I would consider this a bug fix.
@sindresorhus If you want I can fix this before v3 (#387) because if we change the return to integrate the indexes it becomes a bracking change.
@skarab42 That would be great 👍