nathanagez
nathanagez

Reputation: 36

Typescript assert function to avoid Non-Null Assertion Operator ! with Objects

based on this post Typescript - What is the best way to type check an object properties and throw upon null?

I'm trying to check if values of my object are not undefined and narrow the type of the argument to a version with all non-null properties but I keep having this issue: "Argument of type '{ Id?: string | undefined; Name?: string | undefined; }' is not assignable to parameter of type 'MyTypeNotNull'."

I would like to know what's wrong with my assert function signature ?

type MyType = {
    Id?: string | undefined
    Name?: string | undefined
};

type MyTypeNotNull = {
    Id: string
    Name: string
};

function logMyType(type: MyTypeNotNull) {
    console.log(type);
}

function assertNoPropsAreUndefined<T extends object>(obj: T): asserts obj is
    { [K in keyof T]: NonNullable<T[K]> } {
    Object.entries(obj).forEach(([k, v]) => {
        console.log(k, v)
        if (v === undefined)
            throw new Error("OH NOEZ, PROP \"" + k + "\" IS NULL");
    });
}

const run = (value: MyType) => {
    value; // (parameter) value: MyType
    assertNoPropsAreUndefined(value)
    value;
    logMyType(value); // should be ok but it throw Argument of type '{ Id?: string | undefined; Name?: string | undefined; }' is not assignable to parameter of type 'MyTypeNotNull'.
};

run({ Id: 'myKey1', Name: "ok" }); // {key1: "myKey1"}

run({ Id: 'myKey1', Name: undefined }); // 💥 OH NOEZ, PROP "key3" IS NULL

Playground link to code

Upvotes: 0

Views: 1741

Answers (1)

nathanagez
nathanagez

Reputation: 36

Thanks @caTS. For others in the same situation I was missing the Required built-in type.

type MyType = {
    Id?: string | undefined
    Name?: string | undefined
};

type MyTypeNotNull = {
    Id: string
    Name: string
};

function logMyType(type: MyTypeNotNull) {
    console.log(type);
}

function assertNoPropsAreUndefined<T extends object>(obj: T): asserts obj is
    Required<{ [K in keyof T]: NonNullable<T[K]> }> {
    Object.entries(obj).forEach(([k, v]) => {
        if (v === undefined)
            throw new Error("OH NOEZ, PROP \"" + k + "\" IS NULL");
    });
}

const run = (value: MyType) => {
    value; // (parameter) value: MyType
    assertNoPropsAreUndefined(value)
    value;
    logMyType(value);
};

run({ Id: 'myKey1', Name: "ok" }); // {key1: "myKey1"}

run({ Id: 'myKey1', Name: undefined }); // 💥 OH NOEZ, PROP "Name" IS NULL

Link to playground

Upvotes: 1

Related Questions