Closed as not planned
Description
π Search Terms
discriminated union return type
π Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about discrimintated union return types
β― Playground Link
π» Code
type Classifier = 'fooString' | 'barNumber';
type ClassifierType<T extends Classifier> = T extends 'fooString'
? string
: number;
type GenericType<T extends Classifier> = {
classifier: T;
value: ClassifierType<T>;
};
type GenericTypeMap = {
fooString: GenericType<'fooString'>;
barNumber: GenericType<'barNumber'>;
};
// use this to create a type a discriminated union: GenericType<'fooString'> | GenericType<'barNumber'>
// as opposed to a non-discimintated union GenericType<'fooString' | 'barNumber'>
type GenericTypeUnion<T extends Classifier> = {
[K in T]: GenericTypeMap[K];
}[T];
type ClassifierTypeMap = {
[K in Classifier]: GenericType<K>['value'];
};
// use this to create a type a discriminated union: ClassifierType<'fooString'> | ClassifierType<'barNumber'>
// as opposed to a non-discimintated union ClassifierType<'fooString' | 'barNumber'>
type ClassifierTypeUnion<T extends Classifier> = {
[K in T]: ClassifierTypeMap[K];
}[T];
function genericFunction<T extends Classifier>(
_classifier: T, // need to pass a dummy classifier var to help the typescript compiler, weird but not what this report is about
input: GenericTypeUnion<T>
): ClassifierTypeUnion<T> {
if (input.classifier === 'fooString') {
return input.value[0];
//. ^^^^^^ ERROR: string is not assignable to type never
} else {
return input.value + 1;
//. ^^^^^^ ERROR: number is not assignable to type never
}
}
const val = genericFunction('fooString', {
//. ^^^ but is correctly inferred as a string here
classifier: 'fooString',
value: 'foo',
});
π Actual behavior
When calling genericFunction
the return type is correctly infered as a string (or number depending on the input).
However inside the function itself: the type checking is not working for return types
π Expected behavior
The type checking should be consistent between the place where the function is called and where the actual function return is defined.
Additional information about the issue
All type checking works as expected where the function is called.
e.g.
// TS knows that the input type (second arg) is not matching the classifier type (first argument)
// TS has inferred that the return type should be a number based on the classifer type (first argument)
const val = genericFunction('barNumber', {
classifier: 'fooString',
value: 'foo',
});
and
// TS knows that the input type value is not matching the classifier type
const val = genericFunction3('fooString', {
classifier: 'fooString',
value: 9,
});