-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Error when passing this
to generic interface where Type Parameter has been extended
#35498
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Technically this is a duplicate of #31251. TLDR: The conditional type in the return of interface ITest<T extends object = object> {
relation: IRelation<this>;
validate<U extends T>(thingToValidate: U): ((x: T) => void) extends ((x: object) => void) ? object : U;
} |
Wow @jack-williams that is spectacularly effective (while also spectacularly confusing 🙂) That's definitely enough for me to roll with for now - thanks a ton! |
Ok - follow up question... I see that your workaround does indeed help us accomplish what we want, but is that ONLY working because of the bug that you linked? When that issue is fixed, will this workaround still work? Another way of asking this: in this conditional, is
|
@jack-williams Do you happen to have any other info in response to my previous follow up question? Basically I'm trying to figure out what the eventual behavior will theoretically be after #31251 is fixed |
Sorry @rdhelms!
The workaround I posted works independently of the bug in #31251, as that only targets conditional types with parameters in The workaround is not 100% perfect because the type as written is fundamentally unsound. In validate<U extends T>(thingToValidate: U): unknown // ignore return to validate<U extends object>(thingToValidate: U): unknown // ignore return which is not sound because the constraint in the target is less specific than the source. A minimal example is: const a: <U extends 3>(x: U) => void = (x) => {
// x can only be 3
}
const b: <U extends number>(x: U) => void = a; // error, otherwise x could be any number The proposed workaround works because check types in conditional types are related bivariantly, so when you measure the variance for the modified version declare const foo: ITest<{ x: 'string' }>;
const bar: ITest<{ x: string }> = foo; That being said, there are currently no PR's planned to address the variance for conditional check-types, so there is nothing planned that will break the workaround. I think alot of code could face regressions if this ever changed. |
Thanks @jack-williams that's a very useful example and discussion. I think I'm only beginning to start to wrap my head around the different contexts and subtleties for how TS checks for invariance, but this helps clarify a few points. I appreciate the notes. |
This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
TypeScript Version: 3.7.2
Search Terms:
Passing this to Generic Interface with extended Type Parameter
Code
Expected behavior:
In the above example, we want the return type of
validate
to be different based on whether the user passed a type parameter to the interface. An intuitive way to test this seems to be to check whether the parameter's default type extends the parameter itself (which theoretically should only be true if the parameter IS the default).Actual behavior:
Mysteriously, as soon as
object extends T
is used for the type ofvalidate
, an error is thrown on thethis
parameter being passed to the genericIRelation
interface. The types in the functions ARE actually shown to be what we want them to be, despite the error.It's possibly worth pointing out that the above example is clearly a simplified example to demonstrate the error. Our actual use case involves trying to have the return type of an interface's function have more specific control over whether an object's keys are required or not. The above example, while likely not useful in the real world, is a very close representation of what we're doing.
Playground Link:
http://www.typescriptlang.org/play/?ssl=1&ssc=1&pln=38&pc=1#code/HYQwtgpgzgDiDGEAEBRATmg9mgIhMmSA3gLABQSlSAlsAC4RoBmCyAkgEoQA2Id1mYAB4AKkggAPBsAAmUJGxHQ6APmLkqmpGh58IMkQAtaAcwBcSERqoBfctcq0GzVgqVQ6o8VIiz5mACMAKwh4OiQAXiRAkLC1UgotSh1efkELTl004TpjKDVKAHpC1AxsCxEATxhkAHJFZVEVWpp5YExwkCgoahNQAO5kOkI6arqGjyEY0NVagDoHLQA3EG5qGT0hAFVvaTlLFQAKXNMRTAA1VfW9Cy2ASgtpsN3ffbEAfmjgmaRbxbsyIsmABXYBhATAJAyTDQAByHS2UAgVRqAAUQGhwMdjMBzG5lHd1IkkvBBB4kCs1hsGDJIkgTri5pTrgxDkRtCBZJgwKisDALABGAAMQqQNkJSGKX1idH+9mJSBBYOySGBSKgKIg6MxYGxpgy7k87Mk4BggwsHjQpjFKkJCSSlFJwHJzOp+jpDJMTKubrZ3lN5qQtUMPG4mBa4qKJWNEgDEAtdCtuLFcrIAPIoEgsFc8PQWDQACFgXR4XQ8D0dLT7VQnIwWIgFFxUhCvJI9vIJqoiQ7tFl9EZ9ZZU4tay4G53Wz4-NKflEnl3q0kUnwIRkmyvBEITvkqFL4eIymhFppXZsdm3XvIREdPWdLlSbkh7rdNHuOkNDHwkAADecvaciN+rRIO0SBhrijBICGOjDgqSrgoIUIwlApaIsiYzalinoGgS3YOk6Lo+notJRJ63oPqy7KYlyPJ8oKIpihKUpUZy0K0Zg-IgcCYABJBNgADRIAExZIAA7pyNIzmEsGaPBKpqtAmqYbq2H4pMMZxgmSYmDadrHlQBHhKekmkTiXrGRAfommAZrxkGIbcGGEZMdG-o2YGlrWgCmgAgCQA
Related Issues:
I've seen various comments that I thought might be related, but they all seem to deal with the contravariance of
keyof
- but I'm not aware of howkeyof
could possibly be related to the above example.The text was updated successfully, but these errors were encountered: