I have a type containing some conditionals (Note this isn't my actual code, but a stripped down version which tries to highlight the issue with the least amount of code)
type A<T> = {
prop: T;
value:
T extends string ? { a: T, b: T } :
T extends number ? { y: T, z: T } :
never
}
Instantiating variables with this type works fine. E.g.
// works
const a_string: A<string> = {
prop: '',
value: { a: '', b: ''}
}
// works
const a_number: A<number> = {
prop: 0,
value: { y: 1, z: 1}
}
// errors (as expected)
const a_mistake: A<number> = {
prop: 0,
value: { a: '', b: '' } <-- Should be { y:number, z: number }
}
My problem lies when I try and create this function:
function myFunc<T extends string>(prop: T): A<T> {
return {
prop,
value: { a: prop, b: prop }
}
}
I cannot understand why this does not work. Typescript complains that what I am returning is not assignable to A:
Type '{ a: T; b: T; }' is not assignable to type 'T extends string ? { a: T; b: T; } : T extends number ? { y: T; z: T; } : never'.ts(2322)
union.ts(33, 3): The expected type comes from property 'value' which is declared here on type 'A<T>'
For the life of me I cannot understand why?
CodePudding user response:
I don't know the answer to why this doesn't work, but for some reason typescript is not able to infer the correct type of value property. A way you can solve this is by using type assertions, since you know that the prop
extends string
:
function myFunc<T extends string>(prop: T) {
return {
prop,
value: { a: prop, b: prop },
} as A<T>;
}
CodePudding user response:
I have overenginered a bit.
All you need to do is to overalod your function.
type A<T> = {
prop: T;
value:
T extends string ? { a: T, b: T } :
T extends number ? { y: T, z: T } :
never
}
function myFunc<Prop extends string | number>(prop: Prop): A<Prop>
function myFunc<Prop extends string | number>(prop: Prop) {
return {
prop,
value: { a: prop, b: prop }
}
}
const result = myFunc('sdf').value.a // ok
const result2 = myFunc(42).value.y // ok
I assume you have a lot of switch
cases in this function, otherwise you don't even need a generic parameter.