仅当使用Exclude <>无法定义参数时,才如何在返回类型中包括undefined?

时间:2019-02-07 16:58:46

标签: typescript

我正试图创建一个函数,该函数仅在参数包含返回值的情况下,才将string包含在number中并返回undefined

这就是我所拥有的(我认为可以使用):

export function test<T extends string | undefined>(a: T)
  :Exclude<boolean | T, string> {
    if (a === undefined)
        return undefined;
    return true;
 }

我希望Exclude<boolean | T, string>string中删除string | undefined,而使undefined或什么都不留(取决于所提供的参数类型),但是该代码不会键入-检查,上面写着:

  

类型'undefined'不可分配给类型'boolean | Exclude<T, string>'

2 个答案:

答案 0 :(得分:4)

无法解析的条件类型(例如Exclude<boolean | T, string>T泛型)通常不是可分配的。编译器实际上并不知道如何确定某物是否属于此类,因为它不会尝试遍历泛型T的所有可能实例以查看分配是否安全。因此,在这些情况下,通常assert就是那个类型的值,或者您使用function overloads以便函数实现使用普通的联合类型而不是条件类型。这是断言解决方案:

export function test<T extends string | undefined>(a: T): Exclude<boolean | T, string> {
  if (a === undefined)
    return undefined as Exclude<boolean | T, string>; // asserted
  return true;
}

这是过载解决方案:

export function test<T extends string | undefined>(a: T): Exclude<boolean | T, string>;
// overloaded
export function test(a: string | undefined): boolean | undefined {
  if (a === undefined)
    return undefined;
  return true;
}

只要在使用具体类型的值调用它们时,只要它们按照您希望的方式工作,那么条件类型就应该表现出您所期望的:

const definitelyDefined = test("hey"); // boolean, okay
const maybeUndefined = test(Math.random()<0.5 ? "hey" : undefined); // boolean | undefined, okay

(顺便说一句,我可能会将您的返回类型呈现为boolean | (undefined extends T ? undefined : never)

export function test<T extends string | undefined>(
  a: T
): boolean | (undefined extends T ? undefined : never) {
  if (a === undefined)
    return undefined as (undefined extends T ? undefined : never); // asserted
  return true;
}

但这只是优先事项。

好的,希望能有所帮助;祝你好运!

答案 1 :(得分:1)

您可以使用function overloads来实现。首先,使函数接受任一类型并返回任一种类型,然后添加重载定义以限制可以一起使用的参数和返回类型。

function test(a: string): boolean;
function test(a: undefined): undefined;

function test(a: string | undefined): boolean | undefined {
  if (a === undefined)
    return undefined;

  return true;
}