#How to make a parameter conditionally optional?
24 messages · Page 1 of 1 (latest)
overloads
You can also use spread arguments:
declare function fn<T>(...args: T extends string ? [arg: 42] : []): void
fn<string>()
//
// Expected 1 arguments, but got 0.
fn<string>(42)
fn<number>()
fn<number>(42)
// ^^
// Expected 0 arguments, but got 1.
Thanks so much (had this problem so many times), I think overloads are easier to understand (it's for a library).
!resolved
I think I have to use spread arguments after all because it's for a class construtor.
You can overload constructor as well.
But the generic can't have a different type for each overload, at least this is how I did it:
const symbol = Symbol();
type Symbol = typeof symbol;
function test<Type extends Symbol>(param?: undefined): void;
function test<Type>(param: Type): void;
function test<Type = Symbol>(param: Type | undefined) {}
sure it can, only one of them is instantiated
but since the first overload doesn't use its generic, it isn't inferrable
I don't understand, the last example I gave works, what I meant is that I don't think I can do the same with a class construtor.
It works now with Burrito's answer, I would prefer to overload because it's easier to understand (for the library users) but I don't think it's possible because classes have the generics types and constructor parameters in different places so I can't change one based on the other like with functions.
I'm not sure what this piece of code is supposed to do, but it seems to me it can just be:
function test<T>(param?: T) {}
But yeah, it does sound like an XY problem, you should probably explain what you are actually trying to achieve than your attempted solution.
It's a router that has a state for each request that can be of a custom type, the default is Record<PropertyKey, unknown> and I want it so you don't have to pass an empty object in that case.
I got it working like this:
declare const DATA_BRAND: unique symbol;
type Default = Record<PropertyKey, unknown> & { [DATA_BRAND]: 'something' };
class Router<Data = Default> {
constructor(...[data]: Data extends Default ? [] : [Data]) {}
}
That doesn't work for the case I define a type but not an argument (Router<string>() should be invalid).