The error is technically correct; the callers of your demo2() function is allowed to specify the type parameter T to be whatever they want it to be. This means a call like the following will not result in a compiler error, yet will easily lead to a runtime error:
const z2 = demo2<{ a: number }>(); // uh oh, no error
z2.a.toFixed(); // no error at compile time but "z2.a is undefined" at runtime
Still, if you think the likelihood of someone doing that (manually specifying a generic type parameter) is low, you can use a type assertion to suppress the error, while at the same time using a generic parameter default so that the compiler will infer {} for T when you leave out the init property:
// assertion with default type parameter
function demo3<T = {}>(init: T = {} as T) {
return init;
}
This gives you the following desirable behavior:
const x3 = demo3(); // {}
const y3 = demo3({ a: 123 }); // {a: number}
while still allowing the following undesirable behavior:
const z3 = demo3<{ a: number }>(); // no compiler error
z3.a.toFixed(); // RUNTIME ERROR!
If you want to prohibit manually specifying T without passing in a value of type T, you might consider using something like an overloaded function with multiple call signatures:
// overload
function demo4(): {};
function demo4<T>(init: T): T;
function demo4(init = {}) {
return init;
}
Here, if a caller leaves out the init parameter, the function is no longer treated as generic; the return type is just {}. On the other hand, if the caller provides an init parameter, then the function is treated just like your original demo() function. The implementation of the function works for either call signature.
This also results in the desirable behavior for "normal" calls:
const x4 = demo4(); // {}
const y4 = demo4({ a: 123 }); // {a: number}
And also gives a compiler warning if someone tries to call it the wrong way:
const z4 = demo4<{ a: number }>(); // compiler error! an argument for init is required
Playground link to code
interface Derived extends Partial<ListVariables>{ bbb: string; }. Try to pass a variable of this type.Twhen the parameter is omitted ?useListVariables<Derived>then you cannot use{}as a default valueListVariablesis, nor am I positive what results you want to see for different uses ofuseListVariables()(e.g., what if someone manually specifies the type parameter vs letting the compiler infer it). Any code that shows what you tried. Thanks!