-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conditional type using never type does not work in generic functions #54806
Comments
I'm not seeing a bug here.
But |
The use case here is to type that a function should never accept a second parameter under certain cirumstances: // type definition
interface EventDispatcher<EventMap extends Record<string, any>> {
<Type extends keyof EventMap>(
...args: [EventMap[Type]] extends [never]
? [type: Type, parameter?: null | undefined]
: null extends EventMap[Type]
? [type: Type, parameter?: EventMap[Type]]
: undefined extends EventMap[Type]
? [type: Type, parameter?: EventMap[Type]]
: [type: Type, parameter: EventMap[Type]]
): boolean;
}
// function definition
declare function createEventDispatcher<EventMap extends Record<string, any> = any>(): EventDispatcher<EventMap>;
// usage
const dispatch = createEventDispatcher<{
requiredParam: string;
noParam: never;
optionalParam: string | null;
}>();
dispatch('requiredParam'); // error, no second param given
dispatch('noParam', 'foo'); // error, second param given I guess I need to rewrite the type to use |
It's actually a fundamental type theoretical limitation - the bottom type |
The definition of declare function neverFn<T>(t: T): string; and you're just making it much more confusing to reason about by saying |
Apologies, I should've made the use case more clear - this is only what I reduced this to. The actual use case can be found in this playground. Essentially the task is to give the user some way to specify that a function when called with a specific string as the first parameter only accepts |
That doesn't seem incorrect either. If we follow the rule-of-thumb that a generic body should work for any valid instantiation of its type parameters, the function's error is correct: // inside a function
function fn<T extends boolean>(t: T) {
const dispatch = createEventDispatcher<{
requiredParam: T;
noParam: never;
optionalParam: string | null;
}>();
dispatch('requiredParam', true);
// Modified to expose
return dispatch;
}
// Sample instantiation
const a = fn(false);
// It's not allowed.
a('requiredParam', true); |
I now understand that this isn't incorrect because I guess at this point this deviated into a question rather than an issue, so I'm going to close this - thanks for the explanation everyone. What I take from this is that you should be very careful where you use |
@dummdidumm A good way to think about it is: “I have a value of type |
That is true - and I also shouldn't use/encourage |
Bug Report
When using a conditional type that checks for the
never
type inside a function with a generic parameter that check is not correctly executed and the type is not narrowed accordingly, even if the generic has a constraint that makes clear that the generic type can't benever
(though it should probably also work without a constraint).🔎 Search Terms
generic function narrow condition type never
Possibly related to #49852 / #53455
🕗 Version & Regression Information
This is the behavior in every version I tried, and I reviewed the FAQ for entries about generic functions and never type
⏯ Playground Link
Playground link with relevant code
💻 Code
🙁 Actual behavior
neverResultFromGeneric
is not correctly narrowed to type string🙂 Expected behavior
neverResultFromGeneric
is correctly narrowed to type stringThe text was updated successfully, but these errors were encountered: