-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Inconsistent behavior with type inference for generic contraints #58009
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 don't see failure here, and it's nothing to do with function test<T extends ExampleType>(param: T) {
param = { property: true };
} You can't assign |
Thank you @whzx5byb you are right. I think the example I have built in my initial post is not effective. I missed probably the key point that is visible in the section "Additional information". I think the following version is the proper example, where I have unrolled ts-essential: // Setup
type ExampleType = { propertyA: boolean; propertyB: number };
type BooleanKeys<T> = {
[Key in keyof T]: T[Key] extends boolean ? Key : never;
}[keyof T];
let booleanKeysCheck1: BooleanKeys<ExampleType> = 'propertyA'; // Compiles, expected.
let booleanKeysCheck2: BooleanKeys<ExampleType> = 'propertyB'; // It doesn't compile, expected.
type KeepBooleanProperties<T> = Pick<T, BooleanKeys<T>>;
let check1: KeepBooleanProperties<ExampleType> = { propertyA: true }; // Compiles, expected.
let check2: KeepBooleanProperties<ExampleType> = { propertyA: true, propertyB: 1 }; // It doesn't compile, expected.
// Test with generic constraints.
function test<T extends ExampleType>(param: KeepBooleanProperties<T>) {
param.propertyA = true; // <--------- It doesn't compile, not expexted.
param.propertyB = 1; // It does not compile, expected.
param = { propertyA: true }; // It does not compile, expected after comment of whzx5byb.
} |
What if |
Really insight full. I haven't considered that case and it makes perfectly sense. Let's take a step aside and avoid assignments. // Setup
type ExampleType = { propertyA: boolean; propertyB: number };
type A<T> = {[Key in keyof T]: Key}[keyof T];
let check1: A<ExampleType> = 'propertyA';
let check2: A<ExampleType> = 'propertyB';
// Test with generic constraints.
function test<T extends ExampleType>(param: A<T>) {
if (param.propertyA) { // It doesn't compile, expected known property, with unknown type.
// Logic...
}
if (param['propertyA']) { // It doesn't compile, expected known property, with unknown type.
// Logic...
}
} I understand that there are many cases about types, so after the example of @jcalz I understand that there are problems deriving types. But It seems to me that the access to that property is not ambiguous, where I could use a type guard function, for example. |
In this example, a legal call is test('propertyA'); I don't understand why we would be expected to be able to access the property |
Yes I messed up the previous example. I did several attempts, and this is the latest example I have: // Setup
type ExampleType = { propertyA: boolean; propertyB: number };
type PickProperties<Type, Value> = Pick<Type, {
[Key in keyof Type]: Type[Key] extends Value ? Key : never;
}[keyof Type]>;
let check1: PickProperties<ExampleType, boolean> = { propertyA: true }; // Compiles, expected.
let check2: PickProperties<ExampleType, boolean> = { propertyA: true, propertyB: 1 }; // It doesn't compile, expected.
// Test with generic constraints.
function test<T extends ExampleType>(param: PickProperties<T, boolean>) {
if(param.propertyA){ // It doesn't compile, not expected.
// Logic
}
}
test({propertyA: true}); // Is there any way to call test without the property "propertyA"? This though is about the same topic mentioned by @jcalz, because I filter the properties based on a type. |
This issue has been marked as "Question" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
🔎 Search Terms
type, type inference, generic constraints
🕗 Version & Regression Information
⏯ Playground Link
Playground here
💻 Code
🙁 Actual behavior
The compiler partially infers the type: it doesn't compile as expected when I do the assignment
param.anotherProperty = true
. This makes me think that there is some understanding of the type thanks to the generic constraint.In the other two lines (17 and 18) it doesn't compile with the corresponding error:
🙂 Expected behavior
I would expect a consistent behavior:
Additional information about the issue
I came out with this example from an unexpected behavior using ts-essential, that has more unexpected behaviors:
The text was updated successfully, but these errors were encountered: