I am currently working on creating a type that includes an optional property based on the generic parameter passed. Here is an example of what I have in mind:
type PartialWhen<Bool, T> = Bool extends true ? Partial<T> : T;
type PartialWhenExtends<Base, Parent, T> = PartialWhen<Base extends Parent ? true : false, T>
type Props<V> = {
value: V
} & PartialWhenExtends<V, string, {
getValue: (item: V) => string
}>
function getPropsValue<V>({ value, getValue }: Props<V>): string {
if (getValue !== undefined) {
return getValue(value);
}
return value;
}
const props1: Props<string> = {
value: '123'
}
console.log(getPropsValue(props1))
const props2: Props<number> = {
value: 123,
getValue: (val) => val.toString()
}
console.log(getPropsValue(props2))
const props3: Props<string> = {
value: 'abc',
getValue: (val) => val.concat(val)
}
console.log(getPropsValue(props3))
The issue arises when attempting to return the value in the getPropsValue
function, where TypeScript shows an error stating:
Type 'V' is not assignable to type 'string'
. Although the required condition for getValue
is checked before this point.
To address this problem, I tried asserting the value
as string
, but also experimented with different versions of partial types definitions and union types without success. Another approach involved checking if the value
is of type string
and returning an empty string if it's not, though this solution doesn't work well with generics.
As I plan to utilize the PartialWhenExtends
frequently, I would like to find a method to avoid assertions throughout the code. Are there any adjustments I can make to the partial types definition so that TypeScript can accurately infer the types? If not, do you have any other suggestions that could be applicable in this scenario?