Typescript:在泛型中表达可选参数

Ром*_*дов 4 generics undefined typescript option-type

显然,在打字稿中,可选参数和未定义的联合类型参数之间存在差异

function test(s: string|undefined) {}

function test2(s?: string) {}

test() // error: An argument for 's' was not provided
test2() // OK
Run Code Online (Sandbox Code Playgroud)

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

// 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.
Run Code Online (Sandbox Code Playgroud)

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

jca*_*alz 6

您可以在休息/扩展位置使用元组以更灵活的方式讨论函数的参数列表:

function generic<T extends any>(...args: Partial<T> extends T ? [t?: T] : [t: T]) { }
Run Code Online (Sandbox Code Playgroud)

如果,当您调用 时generic<T>(),类型T是全可选的并且Partial<T> extends T,则这会减少为(...args: [t?: T]) => void,意思是“长度为 1 的参数列表,其中一个元素是可选的且类型为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
Run Code Online (Sandbox Code Playgroud)

看起来不错!

Playground 代码链接