Description
openedon Jan 2, 2017
TypeScript Version: 2.1.1
Also relates to #12424
I recently spent some time looking at the discussion on a safe navigation ?.
operator in typescript/javascript (see #16, and https://esdiscuss.org/topic/existential-operator-null-propagation-operator). Then it struck me that ES6 proxies could be a solution that didn't require new language operators. Wrote something working together, and also found this existing npm package: https://www.npmjs.com/package/safe-proxy. In summary, you'd be able to write
// Safe (only does actual property access if underlying object is valid)
safe(a).b.c().d[0]
// ...instead of the functionally equivalent but unsafe
a.b.c().d[0]
Now, how do I type annotate this? At first, I thought maybe the new mapped types in Typescript 2.1 could be used, but then I've come to believe that it isn't possible currently (please let me know how to do this otherwise). What I miss is a generalized way of narrowing optional types under ---strictNullChecks
.
For example, let's consider using the mapObject
from the the Typescript 2.1 release wiki writeup, with optional properties:
const names:{ foo: string, bar?: string} = { foo: "" };
mapObject(names, s => s.length)
This results in a TS2345 error (basically bar
can't be optional)
Now, back to the SafeProxy
type. The best I can come up with today is
type SafeProxy<T> = {
[P in keyof T]: SafeProxy<T[P]&any>;
};
...which is marginally better than just any
.
I would want (and need for my example above) to define something like below. NOTE: the assertion operator here is made-up-syntax. I suggested an exclamation mark after the actual type, but this could obviously be debated.
type SafeProxy<T> = {
[P in keyof T]: SafeProxy<T[P]!>;
};
Interestingly it would kind of enable the reverse of Partial<T>
:
// existing in lib.d.ts
type Partial<T> = {
[P in keyof T]?: T[P];
};
// potential
type Complete<T> = {
[P in keyof T]: T[P]!;
}
Side note: As I intend the SafeProxy
class to implement Symbol.toPrimitive
, no trailing __value
or similar would be needed. This seems to play well with typescript primitives though
Some other usages (that I guess all play pretty well with --strictNullChecks
)
- advanced assertion style functions
- default mechanism functions