Hur anropar jag en metod från en generisk i TypeScript?
Jag försöker skapa en funktion som anropar en specificerad metod på ett generiskt objekt.
Detta är vad jag kom på:
type MethodName<S extends Object, M extends keyof S> = S[M] extends Function ? M : never
const callMethod = <S, M extends keyof S>(obj: S, method: MethodName<S, M>) =>
obj[method]()
Men jag får felet detta uttryck kan inte anropas. Även om jag ändrar denna funktion till att bara returnera en specificerad metod kan jag anropa den senare:
const getMethod = <S, M extends keyof S>(obj: S, method: MethodName<S, M>) =>
obj[method]
const obj = {
a: 'hi',
call: () => console.log('hi')
}
getMethod(obj, 'call')
Hur blir jag av med felet i det första fallet?
Svar #1
type MethodName<S extends Object, M extends keyof S> = S[M] extends Function ? M : never;
const getMethod = <S, M extends keyof S>(obj: S, methodName: MethodName<S, M>) => obj[methodName];
const callMethod = <S, M extends keyof S>(obj: S, methodName: MethodName<S, M>) => {
const method = getMethod(obj, methodName);
// typeof here is not just checking types in runtime but to hints TS within the if clause method must be callable
if (typeof method === 'function') {
method();
} else {
throw new Error('This is not supposed to throw if TS does check things for you');
}
};
const obj = {
a: 'hi',
call: () => console.log('hi')
};
callMethod(obj, 'call');
https://www.typescriptlang.org/play?#code/C4TwDgpgBAshwAsD2ATAcgQwLYQDwGUoIAPYCAOxQGcoB5AIwCsIBjYAGliNIuqgGsIIJADMo+AHxQAvOIDaMALrcylGgDEAruTYBLJOSgB+LgC4o5CADcIAJwDcAWABQLlgarAoAc3hxEqDJQBJwwKrw0gsJikgAUSEzm+Jw4AejYEOb+yOk4IbASAJQyUgmMcqk5mDiKTq7O7uSeUCwYADZt2YGy+WEkqnxRouIS8YniKfBVGVlTqNV4yQXF0lIA3i5QWy0eXpXdPn5zKGOMk2kLhXWb27pisaCQw-soMtKyAOQi2noGH8UbZzbYFQF6xK43LYAXyIbSo0EBIO2iFsSAA7hYIBiAKK2VG2WIfAAqCF0NDJFiQXiomjAYCQ8NewCQUBR6KgdygRMIKCQEBoLAQrH4rNJ5G8NBESFsUGEmn+dWBUJcUOuDV2UDKQUR2ww5g+pI+7EhLXabXM4JKOyaSDaEAAdG0kN5CYbCiq1a0Ol0TmVOB8vW0FUA
