打字稿:以泛型表示可选参数

时间:2021-01-29 15:32:04

标签: typescript generics undefined optional

显然在打字稿中,可选参数和undefined联合类型的参数是有区别的

function test(s: string|undefined) {}

function test2(s?: string) {}

test() // error: An argument for 's' was not provided
test2() // OK

我想声明一个泛型函数,根据所提供的类型,它的参数是可选的或必需的。例如:

// Intention: if type is the same as its Partial counterpart then the parameter can be made optional
type MaybeOptional<T> = Partial<T> extends T ? T|undefined : T

type O = {
  name?: string
}

function generic<T extends any>(t: MaybeOptional<T>) {}

generic<O>({name:""})
generic<O>() // error. An argument for 't' was not provided.

如何在 Typescript 中表达这样的意图?我可以通过泛型分配这个“可选”特征吗?

1 个答案:

答案 0 :(得分:0)

您可以使用 tuples in rest/spread positions 以更灵活的方式讨论函数的参数列表:

function generic<T extends any>(...args: Partial<T> extends T ? [t?: T] : [t: T]) { }

如果,当您调用 generic<T>() 时,类型 T 是全可选的且 Partial<T> extends T,这将简化为 (...args: [t?: T]) => void,意思是“长度为一个,其一个元素是可选的,类型为 T",减少为 (t?: T) => void)。另一方面,如果类型 T 不是完全可选的,那么这将简化为 (...args: [t: T])=>void;与之前相同,除了元素是必需的,减少为 (t: T) => void

让我们测试一下:

type O = {
  name?: string
}
generic<O>({ name: "" }); // okay
generic<O>({}); // okay
generic<O>(); // okay

type R = {
  name: string;
}
generic<R>({ name: "" }); // okay
generic<R>({}); // error
generic<R>(); // error

看起来不错!

Playground link to code