I'm trying to create a mapped type from a union type of keys. For the sake of having a minimal example, the types simply map to themselves. The following generic returns the expected result
type Foo<Bar extends string> = {[name in Bar]: name}
type test = Foo<'test1' | 'test2'> //test = {test1: 'test1', test2: 'test2'}
However, i want to remove the string contraint and just return undefined if Bar is not a string. I did this in the following way
type Foo<Bar> = Bar extends string ? {[name in Bar]: name} : undefined
type test = Foo<'test1' | 'test2'>
//expected result: test = {test1: 'test1', test2: 'test2'}
//actual result: test = {test1: 'test1'} | {test2: 'test2'}
test is now a union type instead of a simple mapped type.
Is this expected behavior in typescript or should i file a bug report? And is there any way to get the behavior i want?
P.S. In case it can be of assistance, i'm trying to fix this line.
Yes this is expected behavior, it's often useful feature called distributive conditional types.
But sometimes, like in your example, it gets in the way. The workaround is to wrap Bar type parameter in [] when it's used in condition test:
type Foo1<Bar extends string> = {[name in Bar]: name}
type test1 = Foo1<'test1' | 'test2'> //test1 = {test1: 'test1', test2: 'test2'}
type Foo2<Bar> = [Bar] extends [string] ? {[name in Bar]: name} : undefined;
type test2 = Foo2<'test1' | 'test2'> //test2 = {test1: 'test1', test2: 'test2'}
type test3 = Foo2<1>; // undefined
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With