The Wayback Machine - https://web.archive.org/web/20250530220715/https://github.com/microsoft/TypeScript/issues/42337
Skip to content

mongoose has assignability error after #42248 #42337

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sandersn opened this issue Jan 14, 2021 · 2 comments · Fixed by #42447
Closed

mongoose has assignability error after #42248 #42337

sandersn opened this issue Jan 14, 2021 · 2 comments · Fixed by #42447
Assignees
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status.

Comments

@sandersn
Copy link
Member

To repro: cd DefinitelyTyped/types/mongoose && tsc; observe that there are 74 errors, 2 more than the expected 72.

const locationSchema = new mongoose.Schema({
  name: { type: String, required: true },
  address: String,
  rating: { type: Number, "default": 0, min: 0, max: 5 },
  facilities: [String],
  coords: { type: [Number], index: "2dsphere" },
  openingTimes: [mongoose.Schema.Types.Mixed],
  reviews: [mongoose.SchemaTypes.Mixed],
  notes: [noteSchema]
});
var LocModel = mongoose.model<Location>("Location", locationSchema);
LocModel.create({ address: "foo", coords: [1, 2], facilities: ["foo", "bar"], name: "bar", openingTimes: ["foo"], rating: 10, reviews: ["foo"], notes: [] });

Actual:

At mongoose/test/model.ts:613, errors on openingTimes and reviews:

ERROR: 613:107  expect  [email protected] compile error: 
No overload matches this call.
  The last overload gave the following error.
    Type 'string' is not assignable to type 'never'.
      Type 'string' is not assignable to type 'never'.

Expected: No error; the input type was [mongoose.SchemeTypes.Mixed], which should result in string[] not never[]

Likely related to #42336, although in this case we can't ship with this error in mongoose, which may involve fixing mongoose in some way.

@sandersn sandersn added Bug A bug in TypeScript Needs Investigation This issue needs a team member to investigate its status. labels Jan 14, 2021
@sandersn sandersn added this to the TypeScript 4.2.1 milestone Jan 14, 2021
@xandris
Copy link

xandris commented Jan 19, 2021

Minimal repro:

type T = any extends number ? 1 : 0;
let x: T;
x = 1;
x = 0;

This used to typecheck, but now T is 1. The commit that changed this behavior is:

c3dd845923c34cf12cc00cc0787556c177607507 is the first bad commit
commit c3dd845923c34cf12cc00cc0787556c177607507
Author: Wesley Wigham <[email protected]>
Date:   Tue Jan 12 12:59:52 2021 -0800

    Better detect when typical nondistributive conditionals need to be defered by unwrapping their check
 and extends types (#42248)

@xandris
Copy link

xandris commented Jan 19, 2021

This relates to mongoose because mongoose.DeepMapAsObject<{foo: any[]}> used to result in {foo: any[]} but now results in {foo: never[]}. Here's the definition:

type DeepMapAsObject<T> = T extends object | undefined
? {
    [K in keyof T]: T[K] extends Map<infer KM, infer KV> | undefined
    // if it's a map, transform it into Map | Record
    // only string keys allowed
    ? KM extends string ? Map<KM, DeepMapAsObject<KV>> | Record<KM, DeepMapAsObject<KV>> | [KM, DeepMapAsObject<KV>][] : never
    // otherwise if it's an object or undefined (for optional props), recursively go again
    : T[K] extends object | undefined
      ? DeepMapAsObject<T[K]>
      : T[K]
    }
: T;

Substituting any[] for T:

type DeepMapAsObject<any[]> = { /* since any[] extends object */
    // keyof any[] is number, any[number] is any
    [number]: any extends Map<unknown, unknown> | undefined // these get inferred as unknown
    // if it's a map, transform it into Map | Record
    // only string keys allowed
    ? never // KM is unknown which does not extend string, result is never
    // otherwise if it's an object or undefined (for optional props), recursively go again
    : any extends object | undefined
      ? DeepMapAsObject<any> // not too clear what happens here... I think this becomes { [K in string]: never | any } in previous versions of typescript, and { [K in string]: never } in the current version 
      : any
    };

So you have that conditional type testing whether any extends, and one branch is never and the other is any. Before the commit mentioned, the result was { [K in number]: any | never} which is just { [K in number]: any}. After, it just takes the "true" branch and the type becomes { [K in number]: never }.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status.
Projects
None yet
4 participants