-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Conditional types don't retain type knowledge #29599
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
I think this is working as intended. I'm not entirely sure what you mean by:
IMO, it is much easier to give feedback if you also include why you think this is wrong, in addition to what went wrong---this way feedback can be directly tailored to your concerns. A few things to note in the code: In all cases the generic parameter The So in the
Consequently, you get no errors at the assignment. In the
Consequently, you get an error when assigning a string value to the parameter. |
This is neither here nor there but the idea of a conditional type taking both branches and making a union out of that is... kind of mind-blowing to me for some reason (but makes perfect sense in hindsight). Does it do the same for |
It does not. There is some relevant discussion here: #27418 |
Ahhh, you explained it perfectly @jack-williams. That's what I get for late-night issue submission. I think what I was trying to do (and failing to figure out how) was to have the generic type interface BoolProp</* some way of getting a lazy T */> {
propType: T /* inferred somehow? */;
prop: T extends FunctionConstructor ? (() => boolean) : boolean;
}
// pass
const foo: BoolProp = {
propType: Function,
prop: () => true,
}
// fail
const bar: BoolProp = {
propType: Function,
prop: true,
}
// pass
const baz: BoolProp = {
propType: Boolean,
prop: true,
}
// fail
const xyz: BoolProp = {
propType: Boolean,
prop: () => true,
} That's a contrived/simplified example of what I'm trying to accomplish, but I think it illustrates the issue. |
I'm not sure what you want can be exactly achieved; specifically, the bit where you omit the type parameter in the definition of Off the top of my head I can think of three possible routes forward. A) Hope that partial type inference is merged (#26349) so you can do something like this: interface BoolProp<T> {
propType: T;
prop: T extends FunctionConstructor ? (() => boolean) : boolean;
}
// pass
const foo: BoolProp<_> = {
propType: Function,
prop: () => true,
} B) If type BoolProp =
{ propType: FunctionConstructor; prop: () => boolean } |
{ propType: BooleanConstructor; prop: boolean };
// pass
const foo: BoolProp = {
propType: Function,
prop: () => true,
} C) Use generic function inference as an escape hatch. interface BoolProp<T> {
propType: T;
prop: T extends FunctionConstructor ? (() => boolean) : boolean;
}
function makeBoolProp<T>(x: BoolProp<T>): BoolProp<T> {
return x;
}
// pass
const foo = makeBoolProp({
propType: Function,
prop: () => true,
});
// fail
const bar = makeBoolProp({
propType: Function,
prop: true,
}) Or just suffer the pain of annotating explicitly (I don't think this is that bad). |
TypeScript Version: 3.2.4
Search Terms: "conditional types don't", "generic type keeps", "conditional type retain", "conditional type any", "conditional type interface", "conditional type infer"
Code
Expected behavior:
Actual behavior:
Playground Link: https://www.typescriptlang.org/play/#src=%0D%0Ainterface%20Foo%3CT%20%3D%20any%3E%20%7B%0D%0A%20%20bar%3A%20T%20extends%20number%20%3F%20T%20%3A%20boolean%3B%0D%0A%7D%0D%0A%0D%0Ainterface%20Bar%3CT%20%3D%20any%3E%20%7B%0D%0A%20%20bar%3A%20T%20extends%20number%20%3F%20number%20%3A%20boolean%3B%0D%0A%7D%0D%0A%0D%0Aconst%20qwe%3A%20Foo%20%3D%20%7B%20bar%3A%2012%20%7D%3B%0D%0Aconst%20uio%3A%20Foo%20%3D%20%7B%20bar%3A%20false%20%7D%3B%0D%0Aconst%20rty%3A%20Foo%20%3D%20%7B%20bar%3A%20'blah'%20%7D%3B%0D%0A%0D%0Aconst%20asd%3A%20Bar%20%3D%20%7B%20bar%3A%2012%20%7D%3B%0D%0Aconst%20jkl%3A%20Bar%20%3D%20%7B%20bar%3A%20false%20%7D%3B%0D%0Aconst%20fgh%3A%20Bar%20%3D%20%7B%20bar%3A%20'blah'%20%7D%3B
Related Issues: Not that I can tell!
tsconfig.json:
The text was updated successfully, but these errors were encountered: