-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Inferred return type is incomplete #43331
Comments
well, |
Nope, |
That's a bummer. Is there a way around againts this subtype reduction? Is it even corrent to reduce this? |
Don't use inference and instead provide a type annotation for the return type.
Sure, it is. Both returned objects fulfill the requirements of |
I can't, its all generics and auto generated. This is just simplified version. declare function randomData<R>(generator: () => R): R;
const res = randomData(() => {
if (Math.random() > 0.5) {
return (null as unknown) as DataA;
} else if (Math.random() > 0.2) {
return (null as unknown) as DataB;
} else {
return (null as unknown) as DataC;
}
}); Here user provides data and I don't know types in advance (also simplified version). User actually can return something like |
For example something like this is similar what I need to do: interface Response<T> {
data: T;
}
interface SimpleData {
foo: boolean;
}
interface FullData {
foo: boolean;
bar: number;
other: string;
}
declare function fetchSimple(): Response<SimpleData>;
declare function fetchFull(): Response<FullData>;
declare function fetchAndExtract<R extends Response<any>>(fetcher: () => R): R extends Response<infer T> ? T : never;
const data = fetchAndExtract(() => { // user provide inner callback
if (Math.random() > 0.5) {
return fetchSimple(); // user provide this fn
}
return fetchFull(); // user provide this fn
});
// typeof data = SimpleData ... instead of SimpleData | FullData So this kind of thing is not possible? |
+1, this is confusing behavior. It seems incorrect to reduce here, since that erases extra properties that the developer may need. Here's my example showing it results in unexpected compiler errors (playground): type Foo = {
isFoo: true
}
type SpecialFoo = Foo & {
isSpecialFoo: true
}
type fooMap = {
[fooId: string]: Foo | SpecialFoo
}
const getFooById = (fooMap: fooMap, fooId: string) => { // inferred return type: Foo | null
if (Math.random()) {
return null
}
const foo = fooMap[fooId]
return foo // Foo | SpecialFoo
}
const getSpecialFoo = (state: fooMap, fooId: string) => {
const foo = getFooById(state, fooId) // Foo | null
if (!foo) {
return null
}
if (!('isSpecialFoo' in foo)) {
return null
}
return foo.isSpecialFoo // Property 'isSpecialFoo' does not exist on type 'never'.ts(2339)
} |
This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow. |
Bug Report
π Search Terms
Infer, union, return type
π Version & Regression Information
β― Playground Link
Playground link with relevant code
π» Code
π Actual behavior
fn return type is
TestA
π Expected behavior
fn return type is
TestA | TestB
This happens when TestB have some similarity with TestA. If I remove
foo
from TestB then it works ok.This is simplified example. What I want is union of all posible types.
Or is there other way how to extract that union type?
The text was updated successfully, but these errors were encountered: