Generic function and index types
NickName:rssfrncs Ask DateTime:2018-11-14T19:58:54

Generic function and index types

I'm looking to implement a generic function which accepts a single type argument "T" which is an object. It uses keyof T to specify the first argument to the function "property". Now the part I can't get working, I want to use the type of T[typeof property] to specify the type of the second argument to the function "value".

This gets me close to the ideal usage,

type Person = {
  name: string;
  age: number;
};

function filter<T>(property: keyof T, value: T[typeof property]) {

 return `${property} ${value}`

}

filter<Person>("name", 123);

With the above we get type checking for the "property" argument, correctly restricting it to only "name" or "age". Unfortunately for the value argument it accepts either a number or string, so it seems to be creating a union of all the keyof types of Person.

Any ideas?

Copyright Notice:Content Author:「rssfrncs」,Reproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/53299743/generic-function-and-index-types

Answers
Titian Cernicova-Dragomir 2018-11-14T12:05:26

You need to create a relation between the two parameters, after all you could potentially be passing in multiple keys, and multiple values, why would the compiler asume that value should have the type of the key specified in the property parameter.\n\nTo create the relation you will need an extra type parameter to represent the property as a literal type \n\nfunction filter<T, K extends keyof T>(property: K, value: T[K]) {\n return `${property} ${value}`\n}\n\nfilter<Person, \"name\">(\"name\", 123); // error\nfilter<Person, \"age\">(\"age\", 123); // ok\n\n\nThe problem with the above implementation is that you have to specify the additional type parameter since typescript does not support partial type inference. (Hopefuly it will soon be possible as this issue proposes, it's slated for January 2018 but is has been pushed back several times)\n\nTo fix this inconvenience we can create a function that returns a function and fix the T parameter in the first call and let K be inferred in the second call \n\nfunction filter<T>() {\n return function <K extends keyof T>(property: K, value: T[K]) {\n return `${property} ${value}`\n }\n\n}\nfilter<Person>()(\"name\", 123); // error\nfilter<Person>()(\"age\", 123); // ok\n\n\nOr depending on what you plan to do with filter you can leave the function with two type parameters and use the return type as the source for the inference of T:\n\nfunction filter<T, K extends keyof T>(property: K, value: T[K]) {\n return `${property} ${value}` as IFiler<T>\n}\n\ntype IFiler<T> = string & { _isFilterFor: T } \nclass Query<T> {\n addFilter(f: IFiler<T>) {\n\n }\n}\n\nvar q = new Query<Person>();\n// T will be inferred to Person in filter because we assign in to a parameter expecting IFilter<Person>\nq.addFilter(filter('age', \"\")) //error \nq.addFilter(filter('age', 12)) //ok \n// Same as above but assigning to a variable:\nvar f: IFiler<Person> = filter('age', 12);\nvar f2: IFiler<Person> = filter('age', \"12\");\n",


More about “Generic function and index types” related questions

Generic function and index types

I'm looking to implement a generic function which accepts a single type argument "T" which is an object. It uses keyof T to specify the first argument to the function "property". Now the part I can...

Show Detail

Inheritance in generic types

Can anyone help me in using Where for generic types? I was trying to create a function which does ST with a number of type double or int, so I said it should be generic function. But when I try to ...

Show Detail

Calling Generic Types function

is it possible to call generic types function. if not is there a different approach to something like this. someFunction&lt;T&gt;(){ T.anotherFunction(); } EDIT MyModel model = NetworkClient.

Show Detail

Swift: Specialize method of generic class for function types

For generic free functions I can use overloading, to essentially specialize the function for function types, like this: func foo&lt;T&gt;(_ t: T.Type) { print("T is unknown") } func foo&lt;P&gt;(_...

Show Detail

Is it possible to spread unique generic types in TypeScript?

Is it possible to spread the arguments of a function into an array of generic types? I'm trying to add a TypeScript type to a generic function that takes a function and returns a function. The passed

Show Detail

Create a function with array of object with different generic types and output input types

I've a an object with generic called MyObject&lt;T&gt;. Now suppose an array of MyObject with different generic types like: MyObject&lt;A&gt; MyObject&lt;B&gt; MyObject&lt;C&gt; Is possibi

Show Detail

Make sort function with generic types

I am writing a sort function for the array of objects. The function args are an array of objects and the key. I am new to typescript but I am trying to make types generic. But I am getting this err...

Show Detail

index signature assertion with generic types

i'm building a custom event emitter that accepts a literal string type describing the possible events as a generic type to build an Event -&gt; Callbacks map. of course i could use the builtin Map,...

Show Detail

Iterator design pattern for generic types

I am trying to implement Iterator design pattern for generic type. I can not use generic array to store collection, Can someone help me to design Iterator pattern for generic types. My code here:

Show Detail

Inheriting functions that return generic types

I'm attempting to write two classes, call 'em Parent and Child. parent is an abstract class that defines a function that returns a (sort of) generic type public abstract class Parent { public

Show Detail