UndefinedAsString does exactly what I want, but UndefinedAsString2 does not convert undefined to strings. The question is why?
type UndefinedAsString<T> = T extends undefined ? string : T;
const y: UndefinedAsString<object[] | undefined> = 'test'; // ok
const x: UndefinedAsString<object[]> = 'test'; // fails
type UndefinedAsString2<T extends Record<string, any>> = {
[K in keyof T]: T[K] extends undefined ? string : T[K];
};
const z: UndefinedAsString2<{ x: object[] | undefined }> = { x: 'test' }; // fails
CodePudding user response:
Why does UndefinedAsString
work? Because of distributive conditional types. Each element of the union object[] | undefined
will be distributed individually to UndefinedAsString
. The comparison to undefined
works because T
is always a single type which is either undefined
or not.
Why doesn't UndefinedAsString2
work? Distribution does not take place here. So the union object[] | undefined
will be checked for extending undefined
which is false. You need to switch the order around here to check if undefined
extends T[K]
.
type UndefinedAsString2<T extends Record<string, any>> = {
[K in keyof T]: undefined extends T[K] ? string : T[K];
};