Apparently in typescript there's a difference between optional parameter and parameter of union type with undefined
function test(s: string|undefined) {}
function test2(s?: string) {}
test() // error: An argument for 's' was not provided
test2() // OK
I want to declare a generic function that depending on the provided type would have its parameter optional or required. For example:
// 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.
How can I express such intention in Typescript? Can I assign this 'optional' trait through generics?
You could use tuples in rest/spread positions to talk about a function's argument list in a more flexible way:
function generic<T extends any>(...args: Partial<T> extends T ? [t?: T] : [t: T]) { }
If, when you call generic<T>()
, the type T
is all-optional and Partial<T> extends T
, this reduces to (...args: [t?: T]) => void
, meaning "a list of arguments whose length is one and whose one element is optional and of type T
", which reduces to (t?: T) => void)
. If, on the other hand, the type T
is not all-optional, then this reduces to (...args: [t: T])=>void
; the same as before except the element is required, which reduces to (t: T) => void
.
Let's test it:
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
Looks good!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.