-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
generic parameter with default inferred too strictly since 2.7 #21553
Comments
On a side note, having a generic parameter that can not be inferred is a bad sign. |
Yeah, this is totally because inferring from source |
I think this is related to the problem I'm experiencing since I upgraded to 2.7.2, this used to work with 2.6.2.: //TreeNode that takes custom data
interface TreeNode<T> {
data: T;
}
//TreeView, generic to specify default custom data for TreeNode
interface TreeView<T> {
//lookup a TreeNode by a key provided in the custom data, default to the one provided for the TreeView
//property parameter should be limited to actual keys provided by the generic
getNodeByProperty<K = T>(property: keyof K, value: string): TreeNode<K>
}
//my custom data
interface CustomNodeData {
id: string;
name: string;
}
let tree: TreeView<CustomNodeData>;
let node = tree.getNodeByProperty("id", "123"); //node should be TreeNode<CustomNodeData> with 2.7.2 node is inferred as TreeNode<{id: any}> while 2.6.2 inferred the generic default parameter TreeNode<CustomNodeData> Additionally in 2.7.2, let tree: TreeView<CustomNodeData>;
let node = tree.getNodeByProperty("abc", "123"); again, no error, node is then inferred as TreeNode<{abc: any}> o_O if I remove the keyof and use string: interface TreeView<T> {
getNodeByProperty<K = T>(property: string, value: string): TreeNode<K>
}
let tree: TreeView<CustomNodeData>;
let node = tree.getNodeByProperty("abc", "123"); node is then inferred as: TreeNode<CustomNodeData> I have no idea how or why I can get the behavior of 2.6.2 if I change interface TreeView<T> {
getNodeByProperty<K = T, Y extends keyof K = keyof K>(property: Y, value: string): TreeNode<K>
} But this seems unnecessarily complicated? |
That would be because The issue in the OP is maybe still a bug because when there are multiple |
The simplest form of what you want is probably just: interface TreeView<T> {
getNodeByProperty<K extends keyof T>(property: K, value: string): TreeNode<{[KI in K]?: T[KI]}>
} which states "the first argument is some specific set of the keys of |
TypeScript Version: 2.8.0-dev.20180201
Search Terms: generic parameter default infer keyof 2.7
Code
Expected behavior:
Both calls to
foo()
compile with no errors.Actual behavior:
In the second call, when the generic parameter
T
is not set explicitly, an error occurs:error TS2345: Argument of type '"b"' is not assignable to parameter of type '"a"'
.It seems that since
2.7
, the generic parameter is tightly inferred from the first parameter to be something like{a: string}
, so the default (which would have been compatible with both parameters) is not used.This error does not occur in version
2.6.2
. It does occur in version2.7.1
and2.8.0-dev.20180201
.Playground Link: https://www.typescriptlang.org/play/#src=%0Ainterface%20X%20%7B%0A%20%20a%3A%20string%3B%0A%20%20b%3A%20string%3B%0A%7D%0A%0Afunction%20foo%3CT%20%3D%20X%3E(x%3A%20keyof%20T%2C%20y%3A%20keyof%20T)%20%7B%20%7D%0A%0Afoo%3CX%3E('a'%2C%20'b')%3B%0Afoo('a'%2C%20'b')%3B
Related Issues:
The text was updated successfully, but these errors were encountered: