Когда `instanceof` капризничает

Недавно я разместил заявку на GitHub, но проект, похоже, не очень активен, поэтому я не уверен, что он дойдет до многих коллег-разработчиков.

Вот ссылка на проблему: https://github.com/Urigo/graphql-modules/issues/2337.

Чтобы дать немного контекста, я сейчас работаю над GraphQL API, написанным на TypeScript и использующимgraphql-modulesвызов библиотеки внутри одной из ее функций.

Вот код указанной функции (измененный для добавления протоколирования):

      function isScalarResolver(obj) {
    console.log('obj:', obj, '\nisScalarResolver(obj):', obj instanceof GraphQLScalarType, '\n');
    return obj instanceof GraphQLScalarType;
}

После запуска вот вывод, отображаемый в терминале:

      obj: { now: [Function: now] }
isScalarResolver(obj): false

obj: GraphQLScalarType {
  name: 'DateTime',
  description: 'DateTime scalar type',
  specifiedByURL: undefined,
  serialize: [Function: serialize],
  parseValue: [Function: parseValue],
  parseLiteral: [Function: parseLiteral],
  extensions: [Object: null prototype] {},
  astNode: undefined,
  extensionASTNodes: []
}
isScalarResolver(obj): false

Мне кажется, чтоobjэто пример такогоobj instanceof GraphQLScalarTypeдолжен вернутьсяtrue(что на самом деле имеет место при запуске).

Для тех, кто хочет разобраться в этой проблеме, на StackBlitz есть воспроизведение: https://stackblitz.com/github/devatina11yb/graphql-modules.

Этапы воспроизведения:

  1. Откройте код на StackBlitz.
  2. Запустите командуopen /home/projects/qgnikzovb.github/node_modules/.pnpm/graphql-modules@2.1.2_graphql@16.6.0/node_modules/graphql-modules/index.mjsв терминале (файл откроется в редакторе).
  3. Изменить функциюisScalarResolverв строке 1859, добавивconsole.log('obj:', obj, '\nisScalarResolver(obj):', obj instanceof GraphQLScalarType, '\n');.
  4. Запустите командуpnpm run testв терминале.
  5. Вы получите результат, упомянутый выше.

Вы также можете убедиться, что код работает без ошибок, выполнив команду в терминале.

Вот результат после запускаpnpm run dev:

      obj: { now: [Function: now] }
isScalarResolver(obj): false

obj: GraphQLScalarType {
  name: 'DateTime',
  description: 'DateTime scalar type',
  specifiedByURL: undefined,
  serialize: [Function: serialize],
  parseValue: [Function: parseValue],
  parseLiteral: [Function: parseLiteral],
  extensions: [Object: null prototype] {},
  astNode: undefined,
  extensionASTNodes: []
}
isScalarResolver(obj): true

obj: {
  now: [Function: now] { [Symbol(metadata)]: { moduleId: 'scalars' } }
}
isScalarResolver(obj): false

obj: GraphQLScalarType {
  name: 'DateTime',
  description: 'DateTime scalar type',
  specifiedByURL: undefined,
  serialize: [Function: serialize] { [Symbol(metadata)]: { moduleId: 'scalars' } },
  parseValue: [Function: parseValue] { [Symbol(metadata)]: { moduleId: 'scalars' } },
  parseLiteral: [Function: parseLiteral] {
    [Symbol(metadata)]: { moduleId: 'scalars' }
  },
  extensions: [Object: null prototype] {},
  astNode: undefined,
  extensionASTNodes: []
}
isScalarResolver(obj): true

РЕДАКТИРОВАТЬ 1

После дальнейших исследований с помощью отладчика выяснилось, чтоGraphQLScalarTypeклассы загружаются из разных файлов:node_modules/.pnpm/graphql@16.6.0/node_modules/graphql/type/definition.jsиnode_modules/.pnpm/graphql@16.6.0/node_modules/graphql/type/definition.mjsвызываяinstanceofвернутьсяfalse.

Это на самом деле известно как опасность двойной упаковки , когда пакеты CJS и ESM загружаются одновременно. Такgraphql-jsявляется источником этой проблемы, и о ней уже неоднократно сообщалось на GitHub.

1 ответ

Обычно это происходит, когда один и тот же пакет установлен несколько раз (по разным путям). Убедитесь, что ваш код и все ваши зависимости импортируют один и тот же модуль из одного и того же места.

Одной из причин может быть то, что у вас установлено несколько зависимостей, которые зависят от разных версий одного и того же пакета (graphql-jsв этом случае). Используйте файл блокировки, чтобы убедиться, что используется только одна версия.

Другие вопросы по тегам