The Problem: I want to write a function that takes an object and the name of a property as parameters. What I want to achieve is that only property names of properties with a specific type are accepted.
Example: In a person object I have fields name:string and age:number, my function should then only be able to be called with the parameters (person, 'name'). This can be achieved by creating this type:
export type OnlyPropertiesWithSpecificType<TYPE, T> = {
[K in keyof T]: T[K] extends TYPE ? K : never;
}[keyof T];
When accessing the property inside the function the type of the property's values should be constrainted like this:
type Person = {
name: string;
age: number;
};
function somePersonFunction(obj: Person, param: OnlyPropertiesWithSpecificType<string, Person>): string {
return obj[param]; // works, obj[param] is of type 'string'
}
However when I try to generify the function, it is no longer type constrainted:
function someGenericFunction<T>(obj: T, param: OnlyPropertiesWithSpecificType<string, T>): string {
return obj[param]; // doesn't work: "TS2322: Type 'T[{ [K in keyof T]: T[K] extends string ? K : never; }[keyof T]]' is not assignable to type 'string'."
}
This is confusing, because the compiler still only accepts property names belonging to properties of type 'string' as param:
someGenericFunction(person, 'name'); // works
someGenericFunction(person, 'age'); // doesn't work
What I tried:
I created a sandbox with the above example: https://codesandbox.io/s/typescript-forked-ypy0b
How do I solve this problem?
It looks like TS hasn't worked out that someGenericFunction
will always return a string
, even though in practice it always will.
However unless you absolutely need the : string
return type annotation from someGenericFunction
, you can just omit it and your code will work as expected.
function someGenericFunction<T>(
obj: T,
param: OnlyPropertiesWithSpecificType<string, T>
) {
return obj[param]; // inferred return type is T[OnlyPropertiesWithSpecificType<string, T>]
}
When called with actual types TS does infer that T[OnlyPropertiesWithSpecificType<string, T>]
will always be assignable to string
, which is why the functions do work.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.