Skip to content

Suggestion: Type assertion operator (!) with mapped types #13253

Closed

Description

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions