-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Invalid "could be instantiated with a different subtype of constraint" error #35858
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
|
|
TS isn't capable of the higher-order reasoning needed to understand that |
I find this usage of In this example, is there any better approach than just doing a type assertion, e.g., function test<T extends {accepted: boolean}>(cb: (value: T) => void) {
return (data: Omit<T, 'accepted'>) => {
const newData = {...data, accepted: true} as T;
return cb(newData);
}
} |
Is this here the same problem?
Is easily solved with an |
* Update excluding-props.md Fix the final HOC snippet by adding type coercion. See this Github issue: microsoft/TypeScript#35858 I also change the return type from ReactNode to JSX.Element - see: https://stackoverflow.com/questions/54905376/type-error-jsx-element-type-null-undefined-is-not-a-constructor-functi TS Playground for this fix here: https://www.typescriptlang.org/play/?strictFunctionTypes=false&jsx=1&ssl=1&ssc=1&pln=47&pc=49#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgIilQ3wG4AoczAVwDsNgJa4B3YGACwHkXakoAFBF78AXHADOMKMFoBzAJRwA3uThwiMalGY16MRswA8AFThIAHjCS0AJhJVxhfKOKkz5cAL4A+AWvU4AGFcSD5aGHFkdBgAOhDwJhsYEwBPMCRTHwClVUCNJC0dOD0GJjgBMBwwCXEuEHZTABoCZ358HyVxACkAZQANWIBRABskEGSVAPyAehmAQTgYdKQ4NAh+NEM4YAc+NDQkCQkUKFS4ACMkNBRqCVW0jN60GTB4Ww2JWgByeABrWjCJYcFDwTireqNEwtfBtKAdOAAahUcPEsXRXjgAF44CZpoF1rQpHA+CwAArVBw45RwdGxKoQGotOHeOAoBwmCj5dSabTGBJhSbKOmkimMiSYmY+LmBLwyuXkLyUZYZYKgsU1bFTdQjYAANyO4lo1BAVygMtRkmksjkFAVpQM5SCoIENN1BokzJEUG84mdMA1ElyAV5xX8+SMtn12W5KnwBCVsYAskhhOJlO6jl4WjwXOm4YnAkYZlG9TG4Ao7ZRCcTc0hbP6tWxOHXBPgJCxUhZ8AoBP7K5QjI3MxIscoAJyYuFY9ud7twKWkBczYG7SQcCDUEa2S6rTCyJDkIx1huguAjseTpzemcdrvxxfL1cOCQbrc7kEGtlLFZDKA4KAjxPYd9SOS9JWlJ9ODXV9N23XcSgPShyBVVYABEIDkQNtRJFAJjca15ACS13BtRUqDoMpmAwuRXVoPCkC9FwvHEGjA2DHlCj5OBI2jOAAHUIAgTB03oiZszgVt829Lxi1LbIlRreATxopt2G4b0BFne9exogdB1UsSkBnfcPnjadtPnR85mfdc4J3K5EL4ICRFsQyGJM4AzOvFxbznB9IJs6CXzfeDP1WFAfwyP8AJcvg3Mw3CJk87zrJXYK7PfBD9z4IA * Update excluding-props.md * Run prettier * Update excluding-props.md Co-authored-by: swyx <shawnthe1@gmail.com>
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 constraint
of type 'T', but 'T' could be instantiated with a different subtype of constraint
'"foo" | "bar"'.
*/
function f<T extends 'foo' | 'bar'>(t: T = 'foo') {} |
@inad9300
Otherwise what happens if
The error message is super accurate here. |
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 |
There's another solution if you don't want to use function test<T>(cb: (value: T & { accepted: boolean }) => void) {
return (data: T) => cb({...data, accepted: true});
} |
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 @dwjohnston's post on SO that pointed me here. Rough! |
@dwjohnston What about this approach? function withOwner(owner: string) {
return function <T extends { owner: string }>(
Component: React.ComponentType<T>
): React.ComponentType<Omit<T, "owner"> & {owner?: never}> {
return function (props) {
const newProps = { ...props, owner };
return <Component {...newProps} />;
};
};
} |
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 type A = {
"id": string
}
function test<T extends A>(a: T): T {
a.id = "other"
return a
} even if i use type B = {
"id": "test"
}
const b : B = {"id": "test"}
const c = 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 |
Locking since this is garnering a lot of off-topic discussion not really related to the original post |
TypeScript Version: 3.7.2, also tested in nightly (3.8.0-dev.20191224)
Search Terms:
"is assignable to the constraint of type", "could be instantiated with a different subtype of constraint"
Code
Expected behavior:
No error
Actual behavior:
Playground Link: http://www.typescriptlang.org/play/?ts=3.8.0-dev.20191224&ssl=1&ssc=1&pln=4&pc=1#code/GYVwdgxgLglg9mABFApgZygHgCqJQD1TABM1EBvAQwghQAdViAuRAIzjgBsVKwBfAHwAKCKxZCAbpU4gULbAEpEAXgGIJcGMSXkAUIkQAnFFBCGkQ4pSiUWAeQC2MLNgA0iAOTVaDFMQ8CSqqIokLkAHSRVjbu3vSMLFCGsnwKANy6fLpAA
Related Issues:
The text was updated successfully, but these errors were encountered: