Open ghost opened 5 years ago
This isn't really specific to JS, even in TS in master
,
declare function uniq<T>(p: (left: T, right: T) => boolean): (xs: T[]) => T[];
uniq((x, y) => x == y)([1, 3, 3, 7]);
shows uniq
's signature as function uniq<unknown>(p: (left: unknown, right: unknown) => boolean): (xs: unknown[]) => unknown[]
.
@ahejlsberg was an invocation like this supposed to be covered in the recent higher order function assignability stuff? It certainly looks similar to many of those.
@weswigham am I right then in thinking there's actually no way to type this function in actual typescript either?
My attempt was something like this, but T wasn't available across all the parameters.
const uniq = (equals: <T>(left: T, right: T) => boolean) => (xs: T[]): T[] => {
const seen: T[] = []
const out = []
const len = xs.length
let j = 0
for(let i = 0; i < len; i++) {
const item = xs[i]
if(!seen.some(s => equals(s, item))) {
seen.push(item)
out[j++] = item
}
}
return out;
}
const uniq = <T>(equals: (left: T, right: T) => boolean) => (xs: T[]): T[] => {
const seen: T[] = []
const out = []
const len = xs.length
let j = 0
for(let i = 0; i < len; i++) {
const item = xs[i]
if(!seen.some(s => equals(s, item))) {
seen.push(item)
out[j++] = item
}
}
return out;
}
you should just be able to attach T
to the outermost function. But as I said, we still don't infer the right types on usage.
Thanks for the clarification, I wrongly assumed it was a checkJs
issue. I'll just use @ts-ignore for now.
A simpler example that illustrates the issue:
declare function foo<T>(f: (x: T) => void): (x: T) => void;
let func: (x: { foo: 'hello' }) => void = foo(x => x.foo); // Ok
foo(x => x.foo)({ foo: 'hello' }); // Error
In the assignment to func
we infer from the type of func
to the return type of foo
which in turn gives us a contextual type for x
. However, when the function is immediately invoked, we make no inferences from the arguments of the rightmost call, but it is potentially feasible. I'll mark this issue as a suggestion to do so.
TypeScript Version: 3.4.5
jsdoc checkJs template function parameter
Expected behavior: Typechecks fine
Actual behavior: Type 'number' is not assignable to type 'T
Playground Link: https://www.typescriptlang.org/play/#src=%2F**%0D%0A%20*%20%40template%20T%0D%0A%20*%20%40param%20%7B(left%3A%20T%2C%20right%3A%20T)%20%3D%3E%20boolean%7D%20equals%0D%0A%20*%20%40returns%20%7B(xs%3A%20T%5B%5D)%20%3D%3E%20T%5B%5D%7D%0D%0A%20*%2F%0D%0Aconst%20uniq%20%3D%20equals%20%3D%3E%20xs%20%3D%3E%20%7B%0D%0A%09%2F**%20%40type%20%7BT%5B%5D%7D%20*%2F%0D%0A%09const%20seen%20%3D%20%5B%5D%0D%0A%09const%20out%20%3D%20%5B%5D%0D%0A%09const%20len%20%3D%20xs.length%0D%0A%09let%20j%20%3D%200%0D%0A%09for(let%20i%20%3D%200%3B%20i%20%3C%20len%3B%20i%2B%2B)%20%7B%0D%0A%09%09const%20item%20%3D%20xs%5Bi%5D%09%09%0D%0A%09%09if(!seen.some(s%20%3D%3E%20equals(s%2C%20item)))%20%7B%09%09%09%0D%0A%09%09%09seen.push(item)%0D%0A%09%09%09out%5Bj%2B%2B%5D%20%3D%20item%0D%0A%09%20%20%20%7D%0D%0A%09%7D%0D%0A%0D%0A%09return%20out%3B%0D%0A%7D%0D%0A%0D%0Auniq((x%2C%20y)%20%3D%3E%20x%20%3D%3D%20y)(%5B1%2C%203%2C%203%2C%207%5D)
Related Issues: This seems related, but I don't think it's it
https://github.com/Microsoft/TypeScript/issues/26883