Reputation: 11508
I want to implement a function that accepts a parameter that might be null or undefined. In other words, if the type can't be null or undefined, then it should throw a compilation error. For example:
type A = string | null; // Valid
type B = CustomInterface | undefined; // Valid;
type C = string; // Invalid;
type D = CustomInterface // Invalid
My use case is for helper functions such as assertDefined
, that I don't want them to accept values that will always be defined.
Example (playground link)
function assertDefined<T/*extends ???*/>(value: T) {
// ...
}
declare let a: A;
declare let b: B;
declare let c: C;
declare let d: D;
assertDefined(a); // Should allow
assertDefined(b); // Should allow
assertDefined(c); // Should not allow
assertDefined(d); // Should not allow
Upvotes: 3
Views: 662
Reputation: 33101
You can do the trick.
interface CustomInterface {
foo: number;
}
type Falsy = null | undefined
type A = string | null; // Valid
type B = CustomInterface | undefined; // Valid;
type C = string; // Invalid;
type D = CustomInterface // Invalid
function assertDefined<T>(
value: T,
...nullable: T extends null | undefined ? [] : [never]) {
}
const a: A = Math.floor(Math.random() * 11) <= 5 ? 'a' : null;
const b: B = Math.floor(Math.random() * 11) <= 5 ? { foo: 42 } : undefined;
const c: C = 'c';
const d: D = { foo: 42 }
assertDefined(a); // ok
assertDefined(b); // ok
assertDefined(c); // error
assertDefined(d); // error
assertDefined(d, 2); // still error,
In order to achieve desired behaviour I used rest operator.
It means that, if T
can be either null or undefined ...nullable
evaluates to empty array, which is mean that there is no second argument. Otherwise nullable
evaluates to 1 element array [never]
.
But is it possible in this case to pass second argument ?
No! You can't do smth like that in TS. never
means never :D
So, even if you pass second argument it is still error.
Drawback:
assertDefined(d, 2 as never); // valid,
Btw, you can find this answer useful. More interesting examples with type negations you can find in my blog which is dedicated to advanced TS types
Upvotes: 4