-
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
Array cannot infer multiple types with functions #31617
Comments
This is an intentional trade-off so that generics can catch errors where you expect multiple objects to be of the same type, which is usually more common. It doesn't seem like your function needs to be generic at all (it could just be |
Thank you for your answer @RyanCavanaugh ! I just provided a minimal reproduction of the issue. I see your point but I did some more testing and I do not understand why my code above is not working while this code is: type ArgType<T> = { (): T }
type ArgTypes<T> = ArgType<T> | ArgType<T>[]
type ArgDefinition<T> = {
[K in keyof T]: ArgTypes<T[K]>
}
interface Test {
test<T>(args: ArgDefinition<T>): void
}
declare const Test: Test;
Test.test({a: [() => "hello", () => 4]}) And T is correctly inferred as |
It's a matter of whether inference collected multiple candidates or not. The OP has two inference sites, whereas the second example only has one because there's an object property "in the way". |
Thank you @RyanCavanaugh for the explanation ! |
@RyanCavanaugh, is there any documentation on the rules behind TS inferences? I've been playing around with the examples provided here for a while now, and I'm still not sure I fully understand what TS considers "multiple inference sites" (i.e. is it simply a case of |
@RyanCavanaugh re: concrete use case (that I believe ties to this), we're trying to take a function and curry it to remove required properties. Something like: // https://stackoverflow.com/a/61108377/1825390
type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>
interface Payload {
a: number,
b: number,
c: number
}
const emit = (payload: Payload) => null
const addA = (payload: Optional<Payload, 'a'>): Payload => ({ a: 1, ...payload })
const addB = (payload: Optional<Payload, 'b'>): Payload => ({ b: 1, ...payload })
const wrappedEmit = (...funcs) => {
return (partialPayload) => {
const payload = funcs.reduce(...)
return emit(payload)
}
}
const emitWithOnlyC = wrappedEmit(addA, addB)
// only c is required in the payload object now
emitWithOnlyC({c: 1}) I've got a more complete playground example as well. Here's our working-but-too-manual real world example too, if that's helpful. |
TypeScript Version: 3.4.5 & 3.5.0-dev.20190525
Search Terms:
Array infer function generic types
Code
Expected behavior:
I expect no errors and T should be inferred to
string | number
.Actual behavior:
An error appears in the console:
Playground Link:
https://www.typescriptlang.org/play/#src=type%20ArgType%3CT%3E%20%3D%20%7B()%3A%20T%7D%0D%0A%0D%0Atype%20ArgTypes%3CT%3E%20%3D%20ArgType%3CT%3E%20%7C%20ArgType%3CT%3E%5B%5D%0D%0A%0D%0Ainterface%20Test%20%7B%0D%0A%20%20test%3CT%3E(args%3A%20ArgTypes%3CT%3E)%3A%20void%0D%0A%7D%0D%0A%0D%0Adeclare%20const%20Test%3A%20Test%3B%0D%0A%0D%0ATest.test(%5B()%20%3D%3E%20%22hello%22%2C%20()%20%3D%3E%204%5D)
The text was updated successfully, but these errors were encountered: