Reputation: 734
How can I restrict the keys of an object to only those that return a certain type?
In the example below I want to ensure that the type of the property is a function, so that I can execute obj[key]()
.
interface IObj{
p1:string,
p2:number,
p3:()=>void
}
const obj:IObj = {
p1:'str',
p2:5,
p3:()=>void 0
}
function fun<TKey extends keyof IObj>(key: IObj[TKey] extends ()=>void? TKey:never){
const p = obj[key]
p(); // This expression is not callable.
// Not all constituents of type 'string | number | (() => void)' are callable.
// Type 'string' has no call signatures.(2349)
}
Upvotes: 1
Views: 481
Reputation: 184607
You can map the type to property name/never and then index into it, you have half of that already:
type FunctionKeys = {
[K in keyof IObj]: IObj[K] extends () => void ? K : never
}[keyof IObj]; // <-
function fun(key: FunctionKeys) {
const p = obj[key];
p();
}
The indexing will perform a union over all the types of the properties and A | never
is just A
.
(Extracted the type because it's so long. Maybe there is a more elegant method.)
Upvotes: 2