给定类型 "anything except function OR function",我如何检查它是否是 TypeScript 中的函数?
Given the type "anything except function OR function", how do I check if it's a function in TypeScript?
为什么 value
在 if (typeof value === 'function')
检查后不是 () => string
类型?
应该进行什么检查,以便正确推断类型(使强制转换变得不必要)?
function foo<T extends {}>(value: Exclude<T, Function> | (() => string)) {
let result: string;
if (typeof value === 'function') {
result = value(); // Error: Type '(() => string) | (Exclude<T, Function> & Function)' has no compatible call signatures.
result = (value as () => string)(); // works, but I don't like it
} else {
result = value.toString();
}
console.log(result);
}
问题是 typescript 无法对条件类型进行大量推理,而其中仍有未解析的参数(例如函数内部的 T
)。因此,当遇到类型保护时,typescript 只会将参数类型与 Function
相交,导致 (() => string) | (Exclude<T, Function> & Function)
仍然不可调用。
到目前为止,解决这个问题的最简单方法是使用类型断言。
你也可以用不同的方式表达条件。一个函数必须有一个 call
方法。如果我们将 T
约束为,如果它有一个 call
成员,它是与函数中的 call
不兼容的类型,我们实际上将 T
排除在外功能:
function foo<T extends number | string | boolean | null | undefined | ({ call?: undefined; [k: string]: any }) = never>(value: T | (() => string)) {
let result: string;
if (typeof value === 'function') {
result = value(); // ok
} else {
result = value.toString();
}
console.log(result);
}
foo(1)
foo({
o: ""
})
foo(() => "");
foo(() => 1); // error
也许新的 negated types features 会提高 typescript 在涉及类型参数时进行推理的能力。虽然 Exclude
可以很好地过滤类型,但它不能 100% 替代否定类型。
为什么 value
在 if (typeof value === 'function')
检查后不是 () => string
类型?
应该进行什么检查,以便正确推断类型(使强制转换变得不必要)?
function foo<T extends {}>(value: Exclude<T, Function> | (() => string)) {
let result: string;
if (typeof value === 'function') {
result = value(); // Error: Type '(() => string) | (Exclude<T, Function> & Function)' has no compatible call signatures.
result = (value as () => string)(); // works, but I don't like it
} else {
result = value.toString();
}
console.log(result);
}
问题是 typescript 无法对条件类型进行大量推理,而其中仍有未解析的参数(例如函数内部的 T
)。因此,当遇到类型保护时,typescript 只会将参数类型与 Function
相交,导致 (() => string) | (Exclude<T, Function> & Function)
仍然不可调用。
到目前为止,解决这个问题的最简单方法是使用类型断言。
你也可以用不同的方式表达条件。一个函数必须有一个 call
方法。如果我们将 T
约束为,如果它有一个 call
成员,它是与函数中的 call
不兼容的类型,我们实际上将 T
排除在外功能:
function foo<T extends number | string | boolean | null | undefined | ({ call?: undefined; [k: string]: any }) = never>(value: T | (() => string)) {
let result: string;
if (typeof value === 'function') {
result = value(); // ok
} else {
result = value.toString();
}
console.log(result);
}
foo(1)
foo({
o: ""
})
foo(() => "");
foo(() => 1); // error
也许新的 negated types features 会提高 typescript 在涉及类型参数时进行推理的能力。虽然 Exclude
可以很好地过滤类型,但它不能 100% 替代否定类型。