Why do you want to use the "non-null assertion operator"?

The status property can either be string | undefined. What about passing an empty string or perhaps assigning a default value when you don't want to specify a value for status?

<Items status={status || ''}/>

Or:

type ItemProps = {
  status?: string;
};

const Items: React.FC<ItemProps> = ({ status = 'statusDefaultValue' }) => <div>Some JSX</div>

It's a bit hard for me to understand your case without knowing the context. Hope this can help.

Answer from HereBeAndre on Stack Overflow
🌐
Sentry
sentry.io β€Ί sentry answers β€Ί react β€Ί how to fix the forbidden non-null assertion in typescript and react?
How to fix the forbidden non-null assertion in TypeScript and React? | Sentry
The Non-null Assertion Operator (Postfix !) assertion removes the null and undefined types from a value. To use it, add the ! symbol after an expression like in the console log example above.
🌐
Medium
medium.com β€Ί @tar.viturawong β€Ί a-note-on-typescript-non-null-assertion-operator-bad8fbe62bba
A note on TypeScript non-null assertion operator | by Tar Viturawong | Medium
March 25, 2019 - If using the new style context, re-declare this in your class to be theReact.ContextType of your static contextType.* static contextType = MyContext * context!: React.ContextType<typeof MyContext> *@deprecated β€” if used without a type annotation, or without static contextType ... It turned out that this operator ! placed after an expression is TypeScript’s non-null assertion operator.
🌐
TypeScript
typescriptlang.org β€Ί docs β€Ί handbook β€Ί release-notes β€Ί typescript-2-0.html
TypeScript: Documentation - TypeScript 2.0
In particular, the null and undefined types are automatically erased from union types in regular type checking mode (because they are subtypes of all other types), and the ! non-null assertion expression operator is permitted but has no effect in regular type checking mode. Thus, declaration files that are updated to use null- and undefined-aware types can still be used in regular type checking mode for backwards compatibility. In practical terms, strict null checking mode requires that all files in a compilation are null- and undefined-aware. TypeScript 2.0 implements a control flow-based type analysis for local variables and parameters.
🌐
Nicotsou
nicotsou.com β€Ί tltr-typescript-non-null-assertion
Dealing With Non-Null Assertions in TypeScript
One great example is to use it in React components: const Favorite = ({ track }) => <div>{track.isFavorite!}</div> Due to the fact that JSX will always ignore null-ish values by design, it’s safe to produce a nullable value, without worrying that something wrong will happen at runtime.
🌐
GitHub
gist.github.com β€Ί JulianG β€Ί 18af9b9ff582764a87639d61d4587da1
Avoiding the Non-null-assertion Operator in React + Mobx + Typescript Projects Β· GitHub
When injecting MobX stores into React components in Typescript, the recommended approach in MobX docs involves declaring optional props (?). This results in having to perform null checks when accessing an injected store, and MobX recommendeds using the non-null assertion operator (!).
Find elsewhere
Top answer
1 of 1
9

A couple of options for you:

  1. Explicitly check that user isn't null and throw if it is

  2. Define a "logged-in" state interface and write a hook that returns it after checking that user isn't null

  3. Define a "logged-in" state interface and write a type assertion function, then use that in Dashboard or the hook

The common theme among them is not just asserting that user isn't null, but proving it at runtime so programming errors using state with null are caught proactively and clearly, rather than being random-seeming "Can't use X of null" errors.

1. Explicit check

Since the user can only see the Dashboard component if they're signed in, and when they're signed in the user context member won't be null, you can check that explicitly:

const { state } = React.useContext(context);
const { user } = state;
if (!user) {
    throw new Error(`ERROR: User reached Dashboard with null 'user' in context`);
}
// ...code uses `user`...

That way, TypeScript knows for the rest of the component code that user is not null, and you get a clear error if a programming error results in trying to use Dashboard when user is null.

2. LoggedInState and a hook

Alternatively, you could define LoggedInState:

interface LoggedInState {
    user: User;
}

and write a reusable hook:

function useLoggedInContext(context: ContextType): LoggedInState {
    const { state } = React.useContext(context);
    if (!state.user) {
        throw new Error(`ERROR: User reached logged-in-only component with null 'user' in context`);
    }
    return state as LoggedInState;
}

That still has a type assertion, but in a single reusable location with runtime code above proving that it's a correct assertion.

Then in Dashboard (and elsewhere):

const { state } = useLoggedIncontext(context);
// ...

3. A type assertion function

You can wrap that up in a type assertion function:

function assertIsLoggedInState(state: State): asserts state is LoggedInState {
    if (!state.user) {
        throw new AssertionError(`'state' has a null 'user' member, expected a logged-in state`);
    }
}

Then either use it directly in Dashboard:

const { state } = React.useContext(context);
assertIsLoggedInState(state);
// ...code can use `state.user`, which TypeScript now knows can't be `null`

or use it in that useLoggedInContext hook:

function useLoggedInContext(context: ContextType): LoggedInState {
    const { state } = React.useContext(context);
    assertIsLoggedInState(state);
    return state; // TypeScript knows this is a LoggedInState
}

As a minor tweak to the first one: If you don't need state for anything else, you can combine those first two statements:

const { state: { user } } = React.useContext(context);
// ...

That only declares user, without declaring state. If you have other things from state that you need, you could add them after user.

🌐
Rip Tutorial
riptutorial.com β€Ί non-null assertions
TypeScript Tutorial => Non-null assertions
Configure typescript project to compile all files in typescript. ... The non-null assertion operator, !, allows you to assert that an expression isn't null or undefined when the TypeScript compiler can't infer that automatically:
🌐
DEV Community
dev.to β€Ί this-is-learning β€Ί typescript-tips-tricks-non-null-assertion-operator-21eb
Typescript - Tips & Tricks - Non-null assertion operator - DEV Community
September 9, 2021 - There are many many times that you have 100% confidence in a property's existence, but typescript does not... Off the top of my head: response data from an api where you know that if property a has a specific value, then property b will not be null. Another example is if you're using something like jsx-control-statements in react: <If condition={myObj?.name != null}> {myObj.name} </If> You can assert that a property exists, but then when you reference it on the next line, typescript is unable to infer from the control statement that myObj is not null.
Top answer
1 of 3
170

It's called the "Non-null assertion operator" and it tells the compiler that x.getY() is not null.

It's a new typescript 2.0 feature and you can read about it in the what's new page, here's what it says:

A new ! post-fix expression operator may be used to assert that its operand is non-null and non-undefined in contexts where the type checker is unable to conclude that fact. Specifically, the operation x! produces a value of the type of x with null and undefined excluded. Similar to type assertions of the forms x and x as T, the ! non-null assertion operator is simply removed in the emitted JavaScript code.

// Compiled with --strictNullChecks
function validateEntity(e?: Entity) {
    // Throw exception if e is null or invalid entity
}

function processEntity(e?: Entity) {
    validateEntity(e);
    let s = e!.name;  // Assert that e is non-null and access name
}

Edit

There's an issue for documenting this feature: Document non-null assertion operator (!)

2 of 3
45

Non-null assertion operator: !

  • You tells the TS compiler that the value of a variable is not null | undefined
  • Use it when you are in possession of knowledge that the TS compiler lacks.

Here is a trivial example of what it does:

let nullable1: null | number;
let nullable2: undefined | string;

let foo  = nullable1! // type foo: number
let fooz = nullable2! // type fooz: string

It basically removes null | undefined from the type


When do I use this?

Typescript is already pretty good at inferring types for example using typeguards:

let nullable: null | number | undefined;

if (nullable) {
    const foo = nullable; // ts can infer that foo: number, since if statements checks this
}

However sometimes we are in a scenario which looks like the following:

type Nullable = null | number | undefined;

let nullable: Nullable;

validate(nullable);

// Here we say to ts compiler:
// I, the programmer have checked this and foo is not null or undefined
const foo = nullable!;  // foo: number

function validate(arg: Nullable) {
    // normally usually more complex validation logic
    // but now for an example
    if (!arg) {
        throw Error('validation failed')
    }
}

My personal advice is to try to avoid this operator whenever possible. Let the compiler do the job of statically checking your code. However there are scenarios especially with vendor code where using this operator is unavoidable.

🌐
SonarSource
rules.sonarsource.com β€Ί typescript β€Ί rspec-2966
TypeScript static code analysis
Unique rules to find Bugs, Vulnerabilities, Security Hotspots, and Code Smells in your TYPESCRIPT code
🌐
TypeScript ESlint
typescript-eslint.io β€Ί rules β€Ί no-non-null-assertion
no-non-null-assertion | typescript-eslint
TypeScript's ! non-null assertion operator asserts to the type system that an expression is non-nullable, as in not null or undefined. Using assertions to tell the type system new information is often a sign that code is not fully type-safe.
🌐
Biome
biomejs.dev β€Ί linter β€Ί rules β€Ί no-non-null-assertion
noNonNullAssertion | Biome
It’s generally better to structure program logic so that TypeScript understands when values may be nullable. ... code-block.ts:5:21 lint/style/noNonNullAssertion FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ⚠ Forbidden non-null assertion.
🌐
Dey Code
deycode.com β€Ί posts β€Ί how-to-fix-the-forbidden-non-null-assertion-in-typescript-and-react
[Fixed] How to fix the forbidden non-null assertion in TypeScript and React? - Typescript
February 22, 2024 - Quick Fix: Instead of using the non-null assertion operator (!), handle the possibility of a null or undefined value by assigning a default value or using optional chaining. While working on a React project in TypeScript, you encountered the β€˜Forbidden non-null assertion’ error.
🌐
Stack Abuse
stackabuse.com β€Ί bytes β€Ί the-non-null-assertion-operator-in-typescript
The Non-Null Assertion Operator in TypeScript
August 19, 2023 - This is where the Non-Null Assertion Operator comes into play. This operator, denoted by an exclamation point (!), tells TypeScript that a variable is certain to be non-null or non-undefined, even though its type might suggest otherwise.