From 7bb8aab3356eb0cc422617998a9e39ec421c95fb Mon Sep 17 00:00:00 2001 From: uzlopak Date: Sun, 16 Jul 2023 14:18:04 +0200 Subject: [PATCH 1/6] simplify and make the issue aware by using expectType instead of expectAssignable --- types/plugin.d.ts | 37 +++++++++------------------- types/plugin.test-d.ts | 56 +++++++++++++++++++++++++----------------- 2 files changed, 45 insertions(+), 48 deletions(-) diff --git a/types/plugin.d.ts b/types/plugin.d.ts index 33883d8..966dcbb 100644 --- a/types/plugin.d.ts +++ b/types/plugin.d.ts @@ -8,6 +8,7 @@ import { RawServerDefault, FastifyTypeProvider, FastifyTypeProviderDefault, + FastifyBaseLogger, } from 'fastify' type FastifyPlugin = typeof fastifyPlugin @@ -48,37 +49,21 @@ declare namespace fastifyPlugin { declare function fastifyPlugin< Options extends FastifyPluginOptions, RawServer extends RawServerBase = RawServerDefault, - TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault + TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, + Logger extends FastifyBaseLogger = FastifyBaseLogger >( - fn: FastifyPluginAsync, - options?: fastifyPlugin.PluginMetadata -): FastifyPluginAsync; + fn: FastifyPluginAsync, + options?: fastifyPlugin.PluginMetadata | string +): FastifyPluginAsync; declare function fastifyPlugin< Options extends FastifyPluginOptions, RawServer extends RawServerBase = RawServerDefault, - TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault + TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, + Logger extends FastifyBaseLogger = FastifyBaseLogger >( - fn: FastifyPluginAsync, - options?: string -): FastifyPluginAsync; - -declare function fastifyPlugin< - Options extends FastifyPluginOptions, - RawServer extends RawServerBase = RawServerDefault, - TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault ->( - fn: FastifyPluginCallback, - options?: fastifyPlugin.PluginMetadata -): FastifyPluginCallback; - -declare function fastifyPlugin< - Options extends FastifyPluginOptions, - RawServer extends RawServerBase = RawServerDefault, - TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault ->( - fn: FastifyPluginCallback, - options?: string -): FastifyPluginCallback; + fn: FastifyPluginCallback, + options?: fastifyPlugin.PluginMetadata | string +): FastifyPluginCallback; export = fastifyPlugin diff --git a/types/plugin.test-d.ts b/types/plugin.test-d.ts index 8593c34..85038f0 100644 --- a/types/plugin.test-d.ts +++ b/types/plugin.test-d.ts @@ -1,6 +1,6 @@ import fastifyPlugin from '..'; -import fastify, { FastifyPluginCallback, FastifyPluginAsync, FastifyError, FastifyInstance, FastifyPluginOptions } from 'fastify'; -import { expectAssignable } from 'tsd' +import fastify, { FastifyPluginCallback, FastifyPluginAsync, FastifyError, FastifyInstance, FastifyPluginOptions, RawServerDefault, FastifyTypeProviderDefault } from 'fastify'; +import { expectType } from 'tsd' import { Server } from "node:https" import { TypeBoxTypeProvider } from "@fastify/type-provider-typebox" @@ -13,15 +13,15 @@ const testSymbol = Symbol('foobar') // Callback const pluginCallback: FastifyPluginCallback = (fastify, options, next) => { } -expectAssignable(fastifyPlugin(pluginCallback)) +expectType(fastifyPlugin(pluginCallback)) const pluginCallbackWithTypes = (fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { } -expectAssignable(fastifyPlugin(pluginCallbackWithTypes)) +expectType>(fastifyPlugin(pluginCallbackWithTypes)) -expectAssignable(fastifyPlugin((fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { })) +expectType>(fastifyPlugin((fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { })) -expectAssignable(fastifyPlugin(pluginCallback, '' )) -expectAssignable(fastifyPlugin(pluginCallback, { +expectType(fastifyPlugin(pluginCallback, '' )) +expectType(fastifyPlugin(pluginCallback, { fastify: '', name: '', decorators: { @@ -34,32 +34,32 @@ expectAssignable(fastifyPlugin(pluginCallback, { })) const pluginCallbackWithOptions: FastifyPluginCallback = (fastify, options, next) => { - expectAssignable(options.foo) + expectType(options.foo) } -expectAssignable>(fastifyPlugin(pluginCallbackWithOptions)) +expectType>(fastifyPlugin(pluginCallbackWithOptions)) const pluginCallbackWithServer: FastifyPluginCallback = (fastify, options, next) => { - expectAssignable(fastify.server) + expectType(fastify.server) } -expectAssignable>(fastifyPlugin(pluginCallbackWithServer)) +expectType>(fastifyPlugin(pluginCallbackWithServer)) const pluginCallbackWithTypeProvider: FastifyPluginCallback = (fastify, options, next) => {} -expectAssignable>(fastifyPlugin(pluginCallbackWithTypeProvider)) +expectType>(fastifyPlugin(pluginCallbackWithTypeProvider)) // Async const pluginAsync: FastifyPluginAsync = async (fastify, options) => { } -expectAssignable(fastifyPlugin(pluginAsync)) +expectType(fastifyPlugin(pluginAsync)) const pluginAsyncWithTypes = async (fastify: FastifyInstance, options: FastifyPluginOptions): Promise => { } -expectAssignable(fastifyPlugin(pluginAsyncWithTypes)) +expectType>(fastifyPlugin(pluginAsyncWithTypes)) -expectAssignable(fastifyPlugin(async (fastify: FastifyInstance, options: FastifyPluginOptions): Promise => { })) -expectAssignable(fastifyPlugin(pluginAsync, '' )) -expectAssignable(fastifyPlugin(pluginAsync, { +expectType>(fastifyPlugin(async (fastify: FastifyInstance, options: FastifyPluginOptions): Promise => { })) +expectType(fastifyPlugin(pluginAsync, '' )) +expectType(fastifyPlugin(pluginAsync, { fastify: '', name: '', decorators: { @@ -72,20 +72,20 @@ expectAssignable(fastifyPlugin(pluginAsync, { })) const pluginAsyncWithOptions: FastifyPluginAsync = async (fastify, options) => { - expectAssignable(options.foo) + expectType(options.foo) } -expectAssignable>(fastifyPlugin(pluginAsyncWithOptions)) +expectType>(fastifyPlugin(pluginAsyncWithOptions)) const pluginAsyncWithServer: FastifyPluginAsync = async (fastify, options) => { - expectAssignable(fastify.server) + expectType(fastify.server) } -expectAssignable>(fastifyPlugin(pluginAsyncWithServer)) +expectType>(fastifyPlugin(pluginAsyncWithServer)) const pluginAsyncWithTypeProvider: FastifyPluginAsync = async (fastify, options) => {} -expectAssignable>(fastifyPlugin(pluginAsyncWithTypeProvider)) +expectType>(fastifyPlugin(pluginAsyncWithTypeProvider)) // Fastify register @@ -100,3 +100,15 @@ server.register(fastifyPlugin(pluginAsyncWithTypes)) server.register(fastifyPlugin(pluginAsyncWithOptions)) server.register(fastifyPlugin(pluginAsyncWithServer)) server.register(fastifyPlugin(pluginAsyncWithTypeProvider)) + +// properly handling callback and async +fastifyPlugin(function (fastify, options, next) { + expectType(fastify) + expectType(options) + expectType<(err?: Error) => void>(next) +}) + +fastifyPlugin(async function (fastify, options) { + expectType(fastify) + expectType(options) +}) \ No newline at end of file From e68e7bed0dc205ed73bea3ed034c2f77749c38b2 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Tue, 18 Jul 2023 03:06:14 +0200 Subject: [PATCH 2/6] fix narrowing partially --- types/plugin.d.ts | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/types/plugin.d.ts b/types/plugin.d.ts index 966dcbb..92cced8 100644 --- a/types/plugin.d.ts +++ b/types/plugin.d.ts @@ -46,24 +46,17 @@ declare namespace fastifyPlugin { * @param fn Fastify plugin function * @param options Optional plugin options */ - declare function fastifyPlugin< - Options extends FastifyPluginOptions, - RawServer extends RawServerBase = RawServerDefault, - TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, - Logger extends FastifyBaseLogger = FastifyBaseLogger ->( - fn: FastifyPluginAsync, - options?: fastifyPlugin.PluginMetadata | string -): FastifyPluginAsync; declare function fastifyPlugin< - Options extends FastifyPluginOptions, - RawServer extends RawServerBase = RawServerDefault, - TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, - Logger extends FastifyBaseLogger = FastifyBaseLogger + Options extends FastifyPluginOptions, + RawServer extends RawServerBase = RawServerDefault, + TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, + Logger extends FastifyBaseLogger = FastifyBaseLogger, + Fn extends FastifyPluginCallback | FastifyPluginAsync = FastifyPluginCallback >( - fn: FastifyPluginCallback, - options?: fastifyPlugin.PluginMetadata | string -): FastifyPluginCallback; + fn: Fn, + options?: fastifyPlugin.PluginMetadata | string +): Fn extends FastifyPluginAsync ? FastifyPluginAsync : FastifyPluginCallback; + export = fastifyPlugin From ed252d5b8b9e4c8bbd0a8689664789b28dc0f27c Mon Sep 17 00:00:00 2001 From: uzlopak Date: Tue, 18 Jul 2023 03:32:49 +0200 Subject: [PATCH 3/6] fix typings --- types/plugin.d.ts | 7 ++++--- types/plugin.test-d.ts | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/types/plugin.d.ts b/types/plugin.d.ts index 92cced8..9c27303 100644 --- a/types/plugin.d.ts +++ b/types/plugin.d.ts @@ -10,6 +10,7 @@ import { FastifyTypeProviderDefault, FastifyBaseLogger, } from 'fastify' +import { IncomingMessage, Server, ServerResponse } from 'http' type FastifyPlugin = typeof fastifyPlugin @@ -48,15 +49,15 @@ declare namespace fastifyPlugin { */ declare function fastifyPlugin< - Options extends FastifyPluginOptions, + Options extends FastifyPluginOptions = Record, RawServer extends RawServerBase = RawServerDefault, TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, Logger extends FastifyBaseLogger = FastifyBaseLogger, Fn extends FastifyPluginCallback | FastifyPluginAsync = FastifyPluginCallback >( - fn: Fn, + fn: Fn extends FastifyPluginAsync ? FastifyPluginAsync : FastifyPluginCallback, options?: fastifyPlugin.PluginMetadata | string -): Fn extends FastifyPluginAsync ? FastifyPluginAsync : FastifyPluginCallback; +): Fn; export = fastifyPlugin diff --git a/types/plugin.test-d.ts b/types/plugin.test-d.ts index 85038f0..3eb9da5 100644 --- a/types/plugin.test-d.ts +++ b/types/plugin.test-d.ts @@ -102,6 +102,12 @@ server.register(fastifyPlugin(pluginAsyncWithServer)) server.register(fastifyPlugin(pluginAsyncWithTypeProvider)) // properly handling callback and async +fastifyPlugin(function (fastify, options, next) { + expectType(fastify) + expectType>(options) + expectType<(err?: Error) => void>(next) +}) + fastifyPlugin(function (fastify, options, next) { expectType(fastify) expectType(options) From ab8cc7610bdec693ec566320ee7d157fdc873332 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Tue, 18 Jul 2023 05:41:11 +0200 Subject: [PATCH 4/6] fix typings --- types/example-async.test-d.ts | 19 ++++++++ types/example-callback.test-d.ts | 19 ++++++++ types/plugin.d.ts | 3 +- types/plugin.test-d.ts | 78 +++++++++++++++++++++++++------- 4 files changed, 101 insertions(+), 18 deletions(-) create mode 100644 types/example-async.test-d.ts create mode 100644 types/example-callback.test-d.ts diff --git a/types/example-async.test-d.ts b/types/example-async.test-d.ts new file mode 100644 index 0000000..87ef057 --- /dev/null +++ b/types/example-async.test-d.ts @@ -0,0 +1,19 @@ +import { FastifyPluginAsync } from "fastify"; + +type FastifyExampleAsync = FastifyPluginAsync; + +declare namespace fastifyExampleAsync { + + export interface FastifyExampleAsyncOptions { + foo?: 'bar' + } + + export interface FastifyExampleAsyncPluginOptions extends FastifyExampleAsyncOptions { + } + export const fastifyExampleAsync: FastifyExampleAsync + export { fastifyExampleAsync as default } +} + +declare function fastifyExampleAsync(...params: Parameters): ReturnType + +export default fastifyExampleAsync \ No newline at end of file diff --git a/types/example-callback.test-d.ts b/types/example-callback.test-d.ts new file mode 100644 index 0000000..c23f1de --- /dev/null +++ b/types/example-callback.test-d.ts @@ -0,0 +1,19 @@ +import { FastifyPluginCallback } from "fastify"; + +type FastifyExampleCallback = FastifyPluginCallback; + +declare namespace fastifyExampleCallback { + + export interface FastifyExampleCallbackOptions { + foo?: 'bar' + } + + export interface FastifyExampleCallbackPluginOptions extends FastifyExampleCallbackOptions { + } + export const fastifyExampleCallback: FastifyExampleCallback + export { fastifyExampleCallback as default } +} + +declare function fastifyExampleCallback(...params: Parameters): ReturnType + +export default fastifyExampleCallback diff --git a/types/plugin.d.ts b/types/plugin.d.ts index 9c27303..71f7beb 100644 --- a/types/plugin.d.ts +++ b/types/plugin.d.ts @@ -55,9 +55,8 @@ declare function fastifyPlugin< Logger extends FastifyBaseLogger = FastifyBaseLogger, Fn extends FastifyPluginCallback | FastifyPluginAsync = FastifyPluginCallback >( - fn: Fn extends FastifyPluginAsync ? FastifyPluginAsync : FastifyPluginCallback, + fn: Fn extends unknown ? Fn extends (...args: any) => Promise ? FastifyPluginAsync : FastifyPluginCallback : Fn, options?: fastifyPlugin.PluginMetadata | string ): Fn; - export = fastifyPlugin diff --git a/types/plugin.test-d.ts b/types/plugin.test-d.ts index 3eb9da5..170a1de 100644 --- a/types/plugin.test-d.ts +++ b/types/plugin.test-d.ts @@ -1,8 +1,10 @@ import fastifyPlugin from '..'; import fastify, { FastifyPluginCallback, FastifyPluginAsync, FastifyError, FastifyInstance, FastifyPluginOptions, RawServerDefault, FastifyTypeProviderDefault } from 'fastify'; -import { expectType } from 'tsd' +import { expectAssignable, expectError, expectNotType, expectType } from 'tsd' import { Server } from "node:https" import { TypeBoxTypeProvider } from "@fastify/type-provider-typebox" +import fastifyExampleCallback from './example-callback.test-d'; +import fastifyExampleAsync from './example-async.test-d'; interface Options { foo: string @@ -16,20 +18,22 @@ const pluginCallback: FastifyPluginCallback = (fastify, options, next) => { } expectType(fastifyPlugin(pluginCallback)) const pluginCallbackWithTypes = (fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { } -expectType>(fastifyPlugin(pluginCallbackWithTypes)) +expectAssignable(fastifyPlugin(pluginCallbackWithTypes)) +expectNotType(fastifyPlugin(pluginCallbackWithTypes)) -expectType>(fastifyPlugin((fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { })) +expectAssignable(fastifyPlugin((fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { })) +expectNotType(fastifyPlugin((fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { })) -expectType(fastifyPlugin(pluginCallback, '' )) +expectType(fastifyPlugin(pluginCallback, '')) expectType(fastifyPlugin(pluginCallback, { fastify: '', name: '', decorators: { - fastify: [ '', testSymbol ], - reply: [ '', testSymbol ], - request: [ '', testSymbol ] + fastify: ['', testSymbol], + reply: ['', testSymbol], + request: ['', testSymbol] }, - dependencies: [ '' ], + dependencies: [''], encapsulate: true })) @@ -45,7 +49,7 @@ const pluginCallbackWithServer: FastifyPluginCallback = (fastif expectType>(fastifyPlugin(pluginCallbackWithServer)) -const pluginCallbackWithTypeProvider: FastifyPluginCallback = (fastify, options, next) => {} +const pluginCallbackWithTypeProvider: FastifyPluginCallback = (fastify, options, next) => { } expectType>(fastifyPlugin(pluginCallbackWithTypeProvider)) @@ -58,16 +62,16 @@ const pluginAsyncWithTypes = async (fastify: FastifyInstance, options: FastifyPl expectType>(fastifyPlugin(pluginAsyncWithTypes)) expectType>(fastifyPlugin(async (fastify: FastifyInstance, options: FastifyPluginOptions): Promise => { })) -expectType(fastifyPlugin(pluginAsync, '' )) +expectType(fastifyPlugin(pluginAsync, '')) expectType(fastifyPlugin(pluginAsync, { fastify: '', name: '', decorators: { - fastify: [ '', testSymbol ], - reply: [ '', testSymbol ], - request: [ '', testSymbol ] + fastify: ['', testSymbol], + reply: ['', testSymbol], + request: ['', testSymbol] }, - dependencies: [ '' ], + dependencies: [''], encapsulate: true })) @@ -83,7 +87,7 @@ const pluginAsyncWithServer: FastifyPluginAsync = async (fastif expectType>(fastifyPlugin(pluginAsyncWithServer)) -const pluginAsyncWithTypeProvider: FastifyPluginAsync = async (fastify, options) => {} +const pluginAsyncWithTypeProvider: FastifyPluginAsync = async (fastify, options) => { } expectType>(fastifyPlugin(pluginAsyncWithTypeProvider)) @@ -117,4 +121,46 @@ fastifyPlugin(function (fastify, options, next) { fastifyPlugin(async function (fastify, options) { expectType(fastify) expectType(options) -}) \ No newline at end of file +}) + +expectAssignable>(fastifyPlugin(async function (fastify: FastifyInstance, options: Options) { })) +expectNotType(fastifyPlugin(async function (fastify: FastifyInstance, options: Options) { })) + +fastifyPlugin(async function (fastify, options: Options) { + expectType(fastify) + expectType(options) +}) + +fastifyPlugin(async function (fastify, options) { + expectType(fastify) + expectType>(options) +}) + +expectError( + fastifyPlugin(async function (fastify, options: Options, next) { + expectType(fastify) + expectType(options) + }) +) +expectAssignable>(fastifyPlugin(function (fastify, options, next) { })) +expectNotType(fastifyPlugin(function (fastify, options, next) { })) + +fastifyPlugin(function (fastify, options: Options, next) { + expectType(fastify) + expectType(options) + expectType<(err?: Error) => void>(next) +}) + +expectError( + fastifyPlugin(function (fastify, options: Options, next) { + expectType(fastify) + expectType(options) + return Promise.resolve() + }) +) + +server.register(fastifyExampleCallback, { foo: 'bar' }) +expectError(server.register(fastifyExampleCallback, { foo: 'baz' })) + +server.register(fastifyExampleAsync, { foo: 'bar' }) +expectError(server.register(fastifyExampleAsync, { foo: 'baz' })) From 0f51d84d237c989d689c645e3271e5f4b5aa67ce Mon Sep 17 00:00:00 2001 From: uzlopak Date: Tue, 18 Jul 2023 05:51:18 +0200 Subject: [PATCH 5/6] fix --- types/plugin.test-d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/plugin.test-d.ts b/types/plugin.test-d.ts index 170a1de..70ec5a7 100644 --- a/types/plugin.test-d.ts +++ b/types/plugin.test-d.ts @@ -1,5 +1,5 @@ import fastifyPlugin from '..'; -import fastify, { FastifyPluginCallback, FastifyPluginAsync, FastifyError, FastifyInstance, FastifyPluginOptions, RawServerDefault, FastifyTypeProviderDefault } from 'fastify'; +import fastify, { FastifyPluginCallback, FastifyPluginAsync, FastifyError, FastifyInstance, FastifyPluginOptions, RawServerDefault, FastifyTypeProviderDefault, FastifyBaseLogger } from 'fastify'; import { expectAssignable, expectError, expectNotType, expectType } from 'tsd' import { Server } from "node:https" import { TypeBoxTypeProvider } from "@fastify/type-provider-typebox" @@ -123,7 +123,7 @@ fastifyPlugin(async function (fastify, options) { expectType(options) }) -expectAssignable>(fastifyPlugin(async function (fastify: FastifyInstance, options: Options) { })) +expectAssignable>(fastifyPlugin(async function (fastify: FastifyInstance, options: Options) { })) expectNotType(fastifyPlugin(async function (fastify: FastifyInstance, options: Options) { })) fastifyPlugin(async function (fastify, options: Options) { From 527e50ba9303d4897e26596f33158b1347664b54 Mon Sep 17 00:00:00 2001 From: Uzlopak Date: Tue, 18 Jul 2023 10:20:57 +0200 Subject: [PATCH 6/6] Apply suggestions from code review --- types/example-async.test-d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/example-async.test-d.ts b/types/example-async.test-d.ts index 87ef057..fe2a1cd 100644 --- a/types/example-async.test-d.ts +++ b/types/example-async.test-d.ts @@ -16,4 +16,4 @@ declare namespace fastifyExampleAsync { declare function fastifyExampleAsync(...params: Parameters): ReturnType -export default fastifyExampleAsync \ No newline at end of file +export default fastifyExampleAsync