如何在 TypeScript 中区分 `(() => any) | undefined` 与单纯的 `() => any`?
我有两种类型:(() => any) | undefined 和 () => any。我想提取函数的返回类型,但仅在该值肯定不是 undefined 的情况下。
我尝试了以下方法:
type IsUndefined<T> = T extends (() => any) ? "no" : "yes";
但当类型不是 undefined 时,这将解析为 "yes" | "no"。我想在不创建联合类型的情况下检测这些类型之间的区别。
请查看这个游乐场链接以获取示例。
这是简短的故事,长故事是我有一个像下面这样的结构体:
type MyStruct = {
optionalHook?: ((...args: any) => any) | undefined,
requiredHook: (...args: any) => any,
}
我想提取可选钩子的返回类型,但仅在它存在时提取。否则,我想提取必需钩子的返回类型。
请参阅此 playground 链接以获取更全面的示例。
答案#1
不确定为什么在 createStruct 中缺少 optionalHook 并不会将 T 推断为 undefined,但我已经通过添加默认泛型参数得到了期望的结果:
// Create the generic struct
type MyStruct<T extends ((...args: any) => any) | undefined, U extends (...args: any) => any> = {
optionalHook?: T,
requiredHook: U,
}
// Utility function for easily creating stucts with the correct type.
// Without this I'd have to type the generic arguments manually for every struct instance.
function createStruct<T extends ((...args: any) => any) | undefined = undefined, U extends (...args: any) => any = (...args: any) => any>(struct: MyStruct<T, U>) {
return struct;
}
const withOptional = createStruct({
optionalHook: () => 5,
requiredHook: () => "hello",
});
const withoutOptional = createStruct({
requiredHook: () => true,
});
// The function for extracting the return type
type getReturnType<T> =
T extends MyStruct<infer O, infer R> ?
O extends (...args: any) => infer OR ?
OR :
R extends (...args: any) => infer RR ? RR : never :
never;
type ResultWithOptional = getReturnType<typeof withOptional>;
type ResultWithoutOptional = getReturnType<typeof withoutOptional>;
TypeScript 游乐场
显式将 optionalHook 设置为 undefined 也可行:
TypeScript 游乐场
答案#2
你可以使用这样的自定义工具:
export const isSet = <T>(value: T | null | undefined): value is T => {
return value != null;
};
然后使用它:
let something; // (() => any) | undefined
if (isSet(something)) {
doSomething(something); // () => any
}
如果你需要相反的情况(即检查一个类型是否未定义),那么你甚至不需要自定义工具函数,你可以使用 lodash —— 可以使用 isUndefined 或 isNil(= 未定义或为空)。
