Repository: TypeScript
Issue: Assert value type guard for dynamic object properties
Labels: Suggestion,Awaiting More Feedback

# Suggestion

<!--
  Please fill in each section completely. Thank you!
-->

## 🔍 Search Terms

<!--
  💡 Did you know? TypeScript has over 2,000 open suggestions!
  🔎 Please search thoroughly before logging new feature requests as most common ideas already have a proposal in progress.
  The "Common Feature Requests" section of the FAQ lists many popular requests: https://github.com/Microsoft/TypeScript/wiki/FAQ#common-feature-requests

  Replace the text below:
-->

- assert
- type guard
- object property
- dynamic

## ✅ Viability Checklist

<!--
   Suggestions that don't meet all these criteria are very, very unlikely to be accepted.
   We always recommend reviewing the TypeScript design goals before investing time writing
   a proposal for ideas outside the scope of the project.
-->
My suggestion meets these guidelines:

* [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
* [x] This wouldn't change the runtime behavior of existing JavaScript code
* [x] This could be implemented without emitting different JS based on the types of the expressions
* [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).


## ⭐ Suggestion

TypeScript recently introduced assertion type guards, like follows:

```typescript
function assertIsDefined<T>(value: T | undefined ): asserts value is T {
  if (value === undefined) {
    throw new AssertionError({ message: `Expected value not to be undefined` });
  }
}

assertIsDefined(value);
```

This is great, but what I would love is for the error message to log the variable name. The first thing I did was change the function to accept an object:

```typescript
function assertIsDefined<T>(obj: { value: T | undefined }): asserts obj is { value: T } {
  const [key, value] = Object.entries(obj)[0];

  if (value === undefined) {
    throw new AssertionError({ message: `Expected "${key}" not to be undefined` });
  }
}

assertIsDefined({ value });
```

However this doesn't work. The compiler sees `value`, and the value within `{ value }` as separate variables.

I would love to take it further, and have multiple assertion checks in one, like:

```typescript
assertIsDefined({ value1, value2 });
```

The type guard could look like:

```typescript
export function assertIsDefined<T>(obj: { [value: string]: T | undefined }): asserts obj is { [value: string]: T } {
  for (const [key, value] of Object.entries(obj)) {
    if (value === undefined) {
      throw new AssertionError({ message: `Expected "${key}" not to be undefined` });
    }    
  }
}
```

<!-- A summary of what you'd like to see added or changed -->

## 📃 Motivating Example

Assertion type guards to work for object properties.

## 💻 Use Cases

The type guard currently only works for values like `value`, but does not recognise that the check on `{ value }` should work. Supporting this would enable dynamic assertion checks, supporting multiple input values as shown from the Suggestions section above.