Skip to content

"is assignable to the constraint of type but could be instantiated with a different subtype of constraint" error with assetion function #39036

Closed
@mateja176

Description

@mateja176

TypeScript Version: 3.9.4

Search Terms:

is assignable to the constraint of type

Code

const isNil = <A extends any>(a: A) => a === undefined || a === null;

type DeepRequired<O extends {}> = {
  [key in keyof O]: O[key] extends {}
    ? DeepRequired<O[key]>
    : NonNullable<O[key]>;
};

export function assertNonNullable<O extends {}>(
  object: O,
): asserts object is DeepRequired<O> { // throws
  Object.entries(object).forEach(([key, value]) => {
    if (typeof value === 'object' && value !== null) {
      assertNonNullable(value);
    }
    if (isNil(value)) {
      throw new Error(`Key ${key} is required, but the provided value is nil`);
    }
  });
}

interface MaybeA {
  a?: number;
}

const a: MaybeA = { a: undefined };

assertNonNullable(a);

const b = a.a;

Expected behavior:

No error is thrown

Actual behavior:

The following error is thrown:

A type predicate's type must be assignable to its parameter's type.
  Type 'DeepRequired<O>' is not assignable to type 'O'.
    'DeepRequired<O>' is assignable to the constraint of type 'O', but 'O' could be instantiated with a different subtype of constraint '{}'.
      Type 'O[key] extends {} ? DeepRequired<O[key]> : NonNullable<O[key]>' is not assignable to type 'O[key]'.
        Type 'DeepRequired<O[key]> | NonNullable<O[key]>' is not assignable to type 'O[key]'.
          Type 'DeepRequired<O[key]>' is not assignable to type 'O[key]'.

Playground Link:

Link

Related Issues:

#29049

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions