In the following code:
type NoArg = {
(): void
}
type OneArg = {
(x:number): void
}
let noArg: NoArg = (x:number)=>{}
let oneArg: OneArg = ()=>{}
Only the first assigned generates a compiler error. I understand why this is the case, because JavaScript allows functions to be passed with less than their complete set of possible arguments, and that’s different than saying the arguments are optional which has to do with how the function is called rather than how it’s passed. See the FAQ.
But that said, is there any way to construct a version of the OneArg interface that will not be compatible with a zero argument function?
I understand this can be done via branding or nominal typing, e.g.,
type OneArg = {
(x:number): void
_brand: “OneArg”
}
But that, or any other type of nominal typing solution, requires doing extra work on assignment (e.g., you have to explicitly add the _brand property to the function).
So my question is—is there any way to construct a type NoArg that will fail the simple assignment let oneArg: OneArg = ()=>{}?
The FAQ linked above says “There is currently not a way in TypeScript to indicate that a callback parameter must be present.“ Does that completely rule out what I want to do here? I’m hoping it doesn’t since this isn’t a callback parameter, but perhaps the rationale is the same.
UPDATE: In the comments below, a question was raised as to whether this could be achieved with a type guard test. The answer, as far as I can tell, is no, because the type overlap means the type guard won't narrow the types. You can see it in this playground.