Когда `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.
Этапы воспроизведения:
- Откройте код на StackBlitz.
- Запустите команду
open /home/projects/qgnikzovb.github/node_modules/.pnpm/graphql-modules@2.1.2_graphql@16.6.0/node_modules/graphql-modules/index.mjs
в терминале (файл откроется в редакторе). - Изменить функцию
isScalarResolver
в строке 1859, добавивconsole.log('obj:', obj, '\nisScalarResolver(obj):', obj instanceof GraphQLScalarType, '\n');
. - Запустите команду
pnpm run test
в терминале. - Вы получите результат, упомянутый выше.
Вы также можете убедиться, что код работает без ошибок, выполнив команду в терминале.
Вот результат после запуска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
в этом случае). Используйте файл блокировки, чтобы убедиться, что используется только одна версия.