关于泛型,我很好奇如何正确键入函数参数。
看下面的基本示例,我有 2 个函数:
- sayHello
& runAnyFunction
现在,第一次调用 sayHello
显然是一个错误,传递给该函数的数据没有 name
参数。完美且符合预期。
问题出在下一部分,我们有一个函数 runAnyFunction
,它将一个函数作为它的第一个参数,obj
作为它的第二个参数,并简单地运行将 obj
作为参数传递的函数。
下面示例中的以下 2 个函数将毫无问题地通过 typescript 检查,这是我的问题。
runAnyFunction<Person>(sayHello, {
name: "Bob"
});
runAnyFunction<Monster>(sayHello, {
size: "HUGE"
});
我知道第二次调用会给我一个 Hello undefined
,这是不希望的。理想情况下,我希望此调用无法通过类型检查,因为这是不允许的。
我的想法是这里的罪魁祸首是 fn
函数参数,因为它自己的 obj
参数将被推断为 any
,但我'为此编写正确的类型有困难。
我知道在这个演示中,我的 runAnyFunction
是一个实际上只运行任何函数的函数,但是如果有一种首选的方式来键入这种性质的函数,我很想知道。
如何正确输入?
代码示例
// demo.ts
type Fn = (obj) => string;
interface Person {
name: string;
}
interface Monster {
size: string;
}
const somePerson: Person = {
name: "Bob"
};
const someMonster: Monster = {
size: "HUGE"
};
sayHello(someMonster); // ERROR, 'name' is missing in type. Sure, expected.
// sayHello requires an obj of type Person
export function sayHello(obj: Person): string {
return `Hello ${obj.name}`;
}
// Simple function that runs any function, passing obj to it
export function runAnyFunction<T>(fn: Fn, obj: T): void {
const res = fn(obj);
console.log(res);
}
// Person has name, this works
runAnyFunction<Person>(sayHello, {
name: "Bob"
});
// I'm passing sayHello, which should require an object with a `name`
// but it does not error
runAnyFunction<Monster>(sayHello, {
size: "HUGE"
});
最佳答案
您还需要使您的 Fn
类型通用:
type Fn<T> = (obj: T) => string;
export function runAnyFunction<T>(fn: Fn<T>, obj: T): void {
const res = fn(obj);
console.log(res);
}
您之前没有收到错误的原因是您的 Fn
类型隐含的第一个参数是 any
类型:
type Fn = (obj) => string; // obj is implicitly of type any
关于typescript - 将函数作为参数传递时如何添加类型安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55203358/