You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
how generic type and type inference works changed #33278
// A *self-contained* demonstration of the problem follows...// Test this by running `tsc` on the command-line, rather than through another build tool such as Gulp, Webpack, etc.exportinterfaceReducers<M>{[doSomething: string]:
|(<Pextendsnever>(state: Readonly<M>,action: P)=>M)|(<PextendsAbstractAction>(state: Readonly<M>,action: P)=>M);}exportdefaultfunctioncreateModel<M,RextendsReducers<M>,EextendsEffects>(model: {namespace: string;state: M;reducers: R;effects?: E;}){
...
}constmodel=createModel({namespace: 'model',state: modelWithEffectsState,reducers: {doSomething: (state,action: {id: number})=>({ ...state})},effects: {}});const{ actions }=model;actions.doSomething({id: 1});
Expected behavior:
from 3.3.+ to 3.5.,
while invoking createModel, the pass-in object's properties state's type determines reducers['doSomething'] first argument's type and its type is the type of modelWithEffectsState,
and reducers['doSomething'] second argument's type is the type of model.actions.doSomething's argument type - really wonderful features by generic and type inference
Actual behavior:
while since 3.6.3 reducers['doSomething'] first argument's type becomes any,
is there any way to recover these features, or changes i can make to make createModel works again?
Our changes to compareSignaturesIdentical cause the signatures to no longer merge in contextual typing (after all, they have distinct, unique type parameters), which then cause state to not have a contextual type applied. This is maybe a little bit too strict for contextual typing, since the type parameters are going to (sometimes, like in this case) become instantiated anyway.
Hmmm, so sadly I think I can only say that this really only worked essentially because of the bug fixed in #32049 - the two signatures really aren't identical - even if we try to do better and produce inferences for P before checking, since one of the constraints is never, the annotation isn't assignable to that one in that case, P becomes never in that signature, and we see that (state: Readonly<{}>, action: never) => {} isn't the same as (state: Readonly<{}>, action: { id: number }) => {}, and today we only make a contextual signature if the component signatures are identical, so... eck. I imagine that's why one of the signatures is has a P extends never rather than just a never, to create the erroneous "identical" behavior, which no longer occurs.
Activity
[-]how function generic type works changed[/-][+]how generic type and type inference works changed[/+]gogoyqj commentedon Sep 6, 2019
and in simpler scenario it works ok
and little complex fail
sandersn commentedon Sep 6, 2019
skipper (@gogoyqj) This might be fixed in 3.6.3. Can you try typescript@next?
gogoyqj commentedon Sep 8, 2019
Nathan Shively-Sanders (@sandersn),thanks for ur suggestion
i've tried
"typescript": "^3.7.0-dev.20190907", but the problem still exists.and i change the generic
R's definitionfrom:
to:
then it works - so does typescript version 3.6.2
weswigham commentedon Sep 11, 2019
Yeah, I can confirm that for
in 3.5,
stateis inferred asReadonly<{}>, while now it'sany.weswigham commentedon Sep 11, 2019
Our changes to
compareSignaturesIdenticalcause the signatures to no longer merge in contextual typing (after all, they have distinct, unique type parameters), which then causestateto not have a contextual type applied. This is maybe a little bit too strict for contextual typing, since the type parameters are going to (sometimes, like in this case) become instantiated anyway.weswigham commentedon Sep 11, 2019
Regressed by #32049, needs a fix like #31029, but to
compareSignaturesIdentical, rather thansignatureRelatedTo.weswigham commentedon Sep 12, 2019
Hmmm, so sadly I think I can only say that this really only worked essentially because of the bug fixed in #32049 - the two signatures really aren't identical - even if we try to do better and produce inferences for
Pbefore checking, since one of the constraints isnever, the annotation isn't assignable to that one in that case,Pbecomesneverin that signature, and we see that(state: Readonly<{}>, action: never) => {}isn't the same as(state: Readonly<{}>, action: { id: number }) => {}, and today we only make a contextual signature if the component signatures are identical, so... eck. I imagine that's why one of the signatures is has aP extends neverrather than just anever, to create the erroneous "identical" behavior, which no longer occurs.gogoyqj commentedon Sep 12, 2019
seems in early version[ 3.3?]
is not compatible with:
but compatible with:
that's why i using union
and since version 3.4, 3.5, 3.6 are both compatible - but 3.6 works little differently
honestly maybe it's a bravo improvement not a bug since version 3.4 and i can simplify my code