如何区分`(() => any) |仅来自 TypeScript 中的 `() => any` 的 undefined`?

How to distinguish `(() => any) | undefined` from just `() => any` in TypeScript?

我有两种类型:(() => any) | undefined() => any。我想提取函数的 return 类型,但前提是该值绝对不是未定义的。

我试过以下方法:

type IsUndefined<T> = T extends (() => any) ? "no" : "yes";

但是当类型不是未定义时,这会解析为 "yes" | "no"。我想在不创建联合的情况下检测这些类型之间的区别。

请参阅 this playground link 示例。

这是短篇故事,长篇故事是我有一个如下所示的结构:

type MyStruct = {
    optionalHook?: ((...args: any) => any) | undefined,
    requiredHook: (...args: any) => any,
}

我想提取可选挂钩的 return 类型,但前提是它存在。否则我想提取所需钩子的 return 类型。

有关更全面的示例,请参阅 this playground link

您可以像这样使用自定义实用程序:

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 or isNil(= 未定义或为空) .

不确定为什么缺少 optionalHook 不会将 T 推断为 createStruct 中的 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 playground

optionalHook 显式设置为 undefined 也有效:

TypeScript playground