Skip to content
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

TypeScript - Importing Mongoose makes string extend Function in 6.0.6 #10746

Closed
Davies-Owen opened this issue Sep 17, 2021 · 2 comments
Closed
Labels
typescript Types or Types-test related issue / Pull Request
Milestone

Comments

@Davies-Owen
Copy link

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
When I import mongoose 6.0.6, the TypeScript compiler incorrectly evaluates string extends Function as true. The issue does not occur with mongoose 6.0.5.

If the current behavior is a bug, please provide the steps to reproduce.

This script can reproduce the issue: with the mongoose import, the script does not compile. If the mongoose import is removed, the script compiles.

import * as Mongoose from 'mongoose'; // Remove this import and the script compiles

type A = string extends Function ? never : string;

let testVar: A;
/*
 * error TS2322: Type 'string' is not assignable to type 'never'.
 */
testVar = 'A string';

tsconfig.json:

{
  "compilerOptions": {
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "declaration": true,
    "experimentalDecorators": true,
    "incremental": true,
    "jsx": "react",
    "lib": ["ES2020"],
    "module": "commonjs",
    "moduleResolution": "node",
    "pretty": true,
    "removeComments": true,
    "resolveJsonModule": true,
    "sourceMap": true,
    "target": "ES2020",
    "traceResolution": false
  }
  "include": ["src"]
}

What is the expected behavior?
string should not extend Function.

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.
Node: v14.16.1
TypeScript: 4.4.3
Mongoose: v6.0.6
MongoDB: v4.1.2

@IslandRhythms IslandRhythms added the can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. label Sep 17, 2021
@vkarpov15 vkarpov15 added this to the 6.0.9 milestone Sep 18, 2021
@vkarpov15 vkarpov15 added typescript Types or Types-test related issue / Pull Request and removed can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. labels Sep 18, 2021
@vkarpov15 vkarpov15 modified the milestones: 6.0.9, 6.0.10 Sep 18, 2021
@vkarpov15
Copy link
Collaborator

I have no idea why, but this is caused by change on line 1530 in this commit: e0fb110 , and adding back T extends Schema<any, any> ? T : fixes this 😕 😕 . We'll fix this for v6.0.10 later this week, but I want to take some time to see if I can come up with a minimal repro and see if this is a bug in TypeScript.

@vkarpov15
Copy link
Collaborator

I tried to create a minimal repro, but no luck. I think the way to go would be to create a simplified version of Mongoose's index.d.ts that triggers this issue, but haven't been able to figure it out. The below index.d.ts attempts to isolate the offending code, but doesn't cause the issue you're seeing.

declare module 'mongoose' {
  class Schema<DocType = any, M = any, TInstanceMethods = {}> {
    constructor(definition?: SchemaDefinition<DocType>, options?: any);
  }

  class SchemaType {}

  namespace Schema {
    namespace Types {
      class String extends SchemaType {}
    }
  }

  class NativeDate extends Date {}

  type SchemaDefinitionProperty<T = undefined> = SchemaDefinitionWithBuiltInClass<T> |
    SchemaTypeOptions<T extends undefined ? any : T> |
    Schema<any, any, any> |
    Schema<any, any, any>[] |
    SchemaTypeOptions<T extends undefined ? any : T>[] |
    Function[] |
    SchemaDefinition<T> |
    SchemaDefinition<T>[];

  type SchemaDefinition<T = undefined> = T extends undefined
    ? { [path: string]: SchemaDefinitionProperty; }
    : { [path in keyof T]?: SchemaDefinitionProperty<T[path]>; };

  type SchemaDefinitionWithBuiltInClass<T> = T extends number
    ? (typeof Number | 'number' | 'Number')
    : T extends string
    ? (typeof String | 'string' | 'String' | typeof Schema.Types.String)
    : T extends boolean
    ? (typeof Boolean | 'boolean' | 'Boolean')
    : T extends NativeDate
    ? (typeof NativeDate | 'date' | 'Date')
    : (Function | string);

  type Unpacked<T> = T extends (infer U)[] ?
    U :
    T extends ReadonlyArray<infer U> ? U : T;
  type AnyArray<T> = T[] | ReadonlyArray<T>;

  export class SchemaTypeOptions<T> {
    type?:
      T extends string | number | boolean | NativeDate | Function ? SchemaDefinitionWithBuiltInClass<T> :
      T extends object[] ? (AnyArray<Schema<any>> | AnyArray<SchemaDefinition<Unpacked<T>>>) :
      T extends string[] ? AnyArray<SchemaDefinitionWithBuiltInClass<string>> | AnyArray<SchemaTypeOptions<string>> :
      T extends number[] ? AnyArray<SchemaDefinitionWithBuiltInClass<number>> | AnyArray<SchemaTypeOptions<number>> :
      T extends boolean[] ? AnyArray<SchemaDefinitionWithBuiltInClass<boolean>> | AnyArray<SchemaTypeOptions<boolean>> :
      T extends Function[] ? AnyArray<SchemaDefinitionWithBuiltInClass<Function>> | AnyArray<SchemaTypeOptions<Unpacked<T>>> :
      T | typeof SchemaType | Schema<any, any, any> | SchemaDefinition<T>;
  }
}

I also found that this issue only affects TypeScript 4.3.x and 4.4.x. This issue doesn't show up in our tests because we're using TypeScript 4.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
typescript Types or Types-test related issue / Pull Request
Projects
None yet
Development

No branches or pull requests

3 participants