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
Invalid "could be instantiated with a different subtype of constraint" error #35858
Argument of type 'Pick<T, Exclude<keyof T, "accepted">> & { accepted: true; }' is not assignable to parameter of type 'T'.
'Pick<T, Exclude<keyof T, "accepted">> & { accepted: true; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{ accepted: boolean; }'.
Even if it was the reason, this would be incorrect from types point of view: cb: (v: T) => void, T extends { accepted: boolean } -> we should be able to call cb with argument of type T & {accepted: true}
TS isn't capable of the higher-order reasoning needed to understand that Exclude<T, k> & { [k]: T[k] } is equivalent to T. You can only make that determination through understanding what Exclude and & actually do at a higher level, but from TS's point of view, Exclude is just a type alias
Reacted by guidelli, David Johnston, Leo Liang, Vadzim Maisiuk, Martin Jakubík, Robbie Moore, Jaka Jančar, Jeremy Snyder, lx4r, Nick Mitchell and 3 more
I would like to expose a simpler example for which an unexpected error is emitted too, that perhaps helps in tracking down the issue here:
/*Type '"foo"' is not assignable to type 'T'. '"foo"' is assignable to the constraintof type 'T', but 'T' could be instantiated with a different subtype of constraint'"foo" | "bar"'.*/functionf<Textends'foo'|'bar'>(t: T='foo'){}
Inlining the type as in your first snippet would not allow type reuse, unfortunately.
Perhaps what should happen is, an error should be issued when the conflicting situation occurs, and not before. With the overall goal of avoiding having to provide generics explicitly as much as possible, I'd be typically writing things like f() or f('bar'). In this case, TypeScript reporting this error before it actually happens hinders type inference, which is one of the best features of the language.
See how the only difference is the extracted props. After messing around for a long time I suspected it was the extracted props, then saw David Johnston (@dwjohnston)'s post on SO that pointed me here. Rough!
I was digging into that Omit problem because it is quite a limitation to use generic types. I am not sure if it is related, but even without using omit i am discovering something that is not consistent.
This, does not seem to generate any error:
even if i use test with a more specific subtype of A
typeB={"id": "test"}constb : B={"id": "test"}constc=test<B>(b)// here c is of type B, but... does not have the key "id": "test"!
Which is even going to generate the an error if i then compare the "id" key:
c.id==="other";// generates : "This condition will always return 'false' since the types '"test"' and '"other"' have no overlap."
Not sure if I should raise another issue with this, but it is the same problem with than with Omit. Typescript should not let you call a function with generics if they contain a constant. Or maybe i am missing something basic here?
Activity
DanielRosenwasser commentedon Dec 26, 2019
Tcould be instantiated with{ accepted: false; }, couldn't it?vadzimmaisiuk commentedon Dec 28, 2019
I believe that's not the reason, changing
accepted: booleantoaccepted: truestill gives the same error: http://www.typescriptlang.org/play/?ts=3.8.0-dev.20191224&ssl=4&ssc=1&pln=1&pc=1#code/GYVwdgxgLglg9mABFApgZygHgCqJQD1TABM1EBvAQwghQAdViAuZAJxBQF8A+ACggBGLXgDdKAGw4tsASkQBebohFwYxOeQBQiRKxRQQrJL2KUolFgHkAtjCzYANIgDk1WgxTFn3OYsSDecgA6ENNzJzd6RhYodi4ZAG5NTk0gAEven if it was the reason, this would be incorrect from types point of view:
cb: (v: T) => void,T extends { accepted: boolean }-> we should be able to callcbwith argument of typeT & {accepted: true}RyanCavanaugh commentedon Jan 13, 2020
TS isn't capable of the higher-order reasoning needed to understand that
Exclude<T, k> & { [k]: T[k] }is equivalent toT. You can only make that determination through understanding whatExcludeand&actually do at a higher level, but from TS's point of view,Excludeis just a type aliasmrcoles commentedon Mar 11, 2020
I find this usage of
Omitto be really useful for HOCs, and found it unintuitive that Typescript runs into this design limitation.In this example, is there any better approach than just doing a type assertion, e.g.,
dwjohnston commentedon Apr 17, 2020
Is this here the same problem?
https://www.typescriptlang.org/play/?ssl=15&ssc=1&pln=1&pc=1#code/C4TwDgpgBAsiAq5oF4oG8BQUoGcD2AthMABYCWAdgOYBiAToQBJ4DGAXLsHZVQNxQYAvhgyhIUACIRuANwgATRJAA88KBAAewCBXk50ggDRQAquq069UeAD4oqAPIEywZSeMBrCCDwAzazb8Iix4FDjAUACGFHik0vDk1PZQygAK5tq6+nBKEDYAFJRgAK7AHFKyCrnKOUjGqTYAlBzpyDaY2HTExXQU6FjYUAB0I0WlhgPY+ESkPPRMrBwARCQQADZreEsDgrwAVgLCIkA
Is easily solved with an
as Passertion.Update excluding-props.md (#219)
inad9300 commentedon May 17, 2020
I would like to expose a simpler example for which an unexpected error is emitted too, that perhaps helps in tracking down the issue here:
(Playground link.)
jakajancar commentedon Jun 24, 2020
Daniel M. (@inad9300)
I'm pretty sure you want just:
Otherwise what happens if
Tis instantiated with'bar'?The error message is super accurate here.
inad9300 commentedon Jun 30, 2020
Inlining the type as in your first snippet would not allow type reuse, unfortunately.
Perhaps what should happen is, an error should be issued when the conflicting situation occurs, and not before. With the overall goal of avoiding having to provide generics explicitly as much as possible, I'd be typically writing things like
f()orf('bar'). In this case, TypeScript reporting this error before it actually happens hinders type inference, which is one of the best features of the language.ro7584 commentedon Jul 1, 2020
There's another solution if you don't want to use
asto castingThanks for my workmate😍
Playground Link
dminkovsky commentedon Jul 20, 2020
This confused me for a long time.
I expected this should work, but it did not.
But this did.
See how the only difference is the extracted props. After messing around for a long time I suspected it was the extracted props, then saw David Johnston (@dwjohnston)'s post on SO that pointed me here. Rough!
artola commentedon Nov 10, 2020
David Johnston (@dwjohnston) What about this approach?
Ryan Cavanaugh (@RyanCavanaugh) Could you please if this is an acceptable way?
https://www.typescriptlang.org/play?strictFunctionTypes=false&jsx=1#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgIilQ3wG4AoczAVwDsNgJa4B3YGACwHkXakoAFBF78AXHADOMKMFoBzAJRwA3uThwiMalGY16MRswA8AFThIAHjCS0AJhJVxhfKOKkz5cAL4A+AWvU4AGFcSD5aGHFkdBgAOhDwJhsYEwBPMCRTHwCFKOI4hLDktIyjLhB2UwAaAmd+fB84ADIVOqgAfnE+ADd+XxUA9U1tXToGJjgBMBwwCSVVQMC0Jik4PhYABRmHAF5HWIPpiFmatu8KRaGkLR04I0KkiJUD2PWt44kvOAB6HwvArz-QHkLyUGDpJDBFAwd6zOB7BZwAA2wF6Ei61BAACN+P82m5pLI5BRgXpxswgtCBMpkaikBJTiIoN5xJSYdt5gFhrd-IsjLZUdlLip8ARQcKALJIYTiZQotFeGo8FyytriwJGb4C7pCuAKEmUZa0VbKpC2Nnw1jsbhMgT4CQsVIWfAKARs-WUe7Q2lonbKACcXzaO3tjudPz+P2+cE4wAcEg4EGoSNscBxcEwsiQ5DKInN3vl9L9gacTJDDqdot+pCjMY4cckieTqY4KF6cBQMYhAFEoDgoDnTfn4IWJMWvtXa7H402U2nIZm+JRyOCMnAACIQOSwhyI2goEBIAkeOQBfGSQnyEFUMYGCabuTU-eHxkuLziB87zlXG7GbWNAB1CAIEwWVnyQRU4FNVxWiZLxNX-a8jRNPMH0tNhOGgu0K2dV0Hw9T00PAkNM1sCBRWDUNKwjGtvmjadGyTOd00XbNcz4WwiIPJASOAMiKLLKjw0nOi6wbBMmJbNtIU7VckF7ftB1Qrc1m43j+Joqd6xnST5wzLMgA
anlauren commentedon Dec 26, 2020
I was digging into that Omit problem because it is quite a limitation to use generic types. I am not sure if it is related, but even without using
omiti am discovering something that is not consistent.This, does not seem to generate any error:
even if i use
testwith a more specific subtype ofAWhich is even going to generate the an error if i then compare the "id" key:
Not sure if I should raise another issue with this, but it is the same problem with than with
Omit. Typescript should not let you call a function with generics if they contain a constant. Or maybe i am missing something basic here?RyanCavanaugh commentedon Mar 2, 2021
Locking since this is garnering a lot of off-topic discussion not really related to the original post