我有一个通用函数类型,如下所示:
type Test<TArg> = (arg: TArg) => void;
大多数时候,参数由符合这种类型的函数使用:
let x1: Test<number> = (n) => { console.log(n) };
let x2: Test<string> = (s) => { alert(s) };
虽然有时候,我有一个不接受任何参数的函数:
let y1: Test<undefined> = () => { };
我希望能够调用此函数而无需在调用点提供任何参数,如下所示:
y1();
但是无论我为 TArg
插入什么类型,我似乎都无法做到这一点。有没有在 Test
的定义中使参数可选的情况下执行此操作?
这是我尝试过的:
type Test<TArg> = (arg: TArg) => void;
let x: Test<number> = (n) => { console.log(n) };
let y1: Test<never> = () => { };
let y2: Test<any> = () => { };
let y3: Test<undefined> = () => { };
let y4: Test<null> = () => { };
x(1);
y1(); //Expected 1 arguments, but got 0.
y2(); //Expected 1 arguments, but got 0.
y3(); //Expected 1 arguments, but got 0.
y4(); //Expected 1 arguments, but got 0.
最佳答案
如果有一个执行包装器是可以接受的,我想出了一个解决方案来处理函数长度(0 或 1),并且对于参数来说是类型安全的:
type Test<T> = (arg?: T) => void;
class Wrapper<T, F extends Test<T>> {
public execute: F;
public static create<T1, F1 extends Test<T1>>(method: F1): Wrapper<T1, F1> {
return new Wrapper(method);
}
constructor(method: F) {
this.execute = method;
}
}
const func1 = Wrapper.create((a: string) => console.log(a));
const func2 = Wrapper.create(() => { });
func1.execute('3');
func2.execute();
func1.execute(5); // 5 is not assignable to type "string"
func1.execute(); // expected 1 argument
func2.execute(5); // expected 0 arguments
请注意,如果您想将其扩展到超过 1 个参数,您可以添加额外的泛型类型,但您必须手动定义每个泛型类型并通过包装类传递它,但它会起作用。
EDIT 删除了原始的可选参数解决方案
关于typescript - 如何在泛型函数类型中拥有可选参数类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48410510/