Don't widen return types of function expressions #241
Comments
|
Bumping this since we ran into a situation with a leaked function forEach<T, U>(array: T[], callback: (element: T, index: number) => U): U {
if (array) {
for (let i = 0, len = array.length; i < len; i++) {
let result = callback(array[i], i);
if (result) {
return result;
}
}
}
return undefined;
}
forEach([1, 2, 3, 4], () => {
// do stuff
if (blah) {
// bam! accidental any
return undefined;
}
}); |
|
We need an implementation proposal for this one. |
|
What if we just did this:
|
|
I've arrived here via #7220. Would appreciate some guidance on whether the following is expected behaviour or not (playground): interface G<K, R> {
(v: K): R;
}
function F<T>(v: T): T {
return v;
}
interface A {
__Type: "A";
}
interface B {
__Type: "B";
}
let a: A;
let b: B;
a = b; // OK: error as expected, B is not assignable to A
b = a; // OK: error as expected, A is not assignable to B
let x: G<A, B> = F; // How is this possible?It's the final assignment I cannot understand... because the compiler does not complain. |
|
During assignment checking, type parameters are replaced with |
|
Time to take this back up since it's affecting a lot of people writing reducers |
export interface Demo {
items?: () => { demo?: string };
}
export const dd: Demo = {
items: (): ReturnType<Required<Demo>['items']> => ({ demo: '1', str: 'error' }),
}; |
|
We've noticed the same issue after some of the reducers returned garbage. Big surprise. function reducer(state: IState, action: IAction): IState {
switch (action.type) {
case 'FOOL_TYPESCRIPT':
return {
...state,
...{ ANY_NON_EXISTING_FIELD_GETS_SWALLOWED_WITH_NO_ERROR: "BOOM" },
};
default:
return state;
}
} |
|
This problem affects any factory function that is intended to create a specific type. (From the form of #12632 ) There's no way to prevent makeOnly from accepting a function returning an object with excess fields. It will detect missing fields, but not excess fields. Thus the user of |
|
@mortoray yes, this is my main issue with this. Currently, the only workaround is to explicitly type the arrow func, which kinda defeats the purpose: |
|
Here is another minimal example of the problem: const getFoo2: () => Foo = {
foo: {
bar: number
}
} => ({
foo: {
bar: 1,
buz: 2, // Doesnt throw an excessive property error
}
})The weird thing is, its not like the function is untyped. Changing the name of |
|
I believe my StackOverflow question relates to this issue: https://stackoverflow.com/questions/63258306/how-to-force-typescript-excess-property-check-on-function-return-value |
|
Hey everyone, I opened #40311 a couple of days ago which I think should fix most of the issues that have brought people here. If you'd like to give it a try, we have a build available over at #40311 (comment). |
|
Hey @DanielRosenwasser, what's the status of your pull request? I suppose I don't have to list any reasons for wanting this feature (there are many discussions), so I'm only curious if there's been any progress recently |
This change courtesy @JsonFreeman who is trying it out
(context elided: widening of function expression return types)
The problem with this widening is observable in type argument inference and no implicit any. For type argument inference, we are prone to infer an any, where we should not:
So after we get to parity, I propose we do the following. We do not widen function expressions. A function is simply given a function type. However, a function declaration (and a named function expression) introduces a name whose type is the widened form of the type of the function. Very simple to explain and simple to implement.
I’ve been told that this would be a breaking change, because types that used to be any are now more specific types. But here are some reasons why it would be okay:
Questions:
Going with 'not a breaking change' here because this is unlikely to break working code, but we need to verify this.
In essence, we already have two types: The original and the widened type. So by that measure this is not really a change
Jason willing to try it out and report back
The text was updated successfully, but these errors were encountered: