You can do it with NonNullable<T>
, but not as a constraint on the type-parameters, but using it as an interface-type on get
‘s R
, like so:
function get<K, R>( o: { get: (key: K) => NonNullable<R> }, key: K ): NonNullable<R> {
return o.get(key);
}
So this code gives me an error:
const params = new Params({ a: 10 });
console.log(get(params, "a"))
Argument of type ‘
Params
‘ is not assignable to parameter of type ‘{ get: (key: "a") => number; }
‘.
The types returned by ‘get(…)’ are incompatible between these types.
Type ‘number | undefined
‘ is not assignable to type ‘number
‘.
Type ‘undefined
‘ is not assignable to type ‘number
‘.(2345)
The catch is that NonNullable<T>
prohibits both undefined
and null
– which may or may not be desirable in your application.
Update
I found the definition of NonNullable<T>
in lib.es6.d.ts
:
/**
* Exclude null and undefined from T
*/
type NonNullable<T> = T extends null | undefined ? never : T;
This can be tweaked to restrict only undefined
:
type NonUndefined<T> = T extends undefined ? never : T;
and if I change get
to this:
type NonUndefined<T> = T extends undefined ? never : T;
function get<K, R>(o: { get: (key: K) => NonUndefined<R> }, key: K): NonUndefined<R> {
return o.get(key);
}
Then this works exactly as you’ve requested: it allows class Params
‘s get
to return number | null
but not number | undefined
.