mirror of
https://github.com/honojs/hono.git
synced 2024-11-21 18:18:57 +01:00
feat(types): allow passing interface
s as Bindings / Variables (#3136)
* feat(types): allow passing `interface`s as Bindings / Variables * test(context): add test for c.var * fix lint warning * test(types): add test for Bindings types
This commit is contained in:
parent
9987b5908f
commit
1cee728193
@ -88,6 +88,13 @@ describe('Context', () => {
|
||||
expect(c.get('foo2')).toBe(undefined)
|
||||
})
|
||||
|
||||
it('c.var', async () => {
|
||||
expect(c.var.foo).toBe(undefined)
|
||||
c.set('foo', 'bar')
|
||||
expect(c.var.foo).toBe('bar')
|
||||
expect(c.var.foo2).toBe(undefined)
|
||||
})
|
||||
|
||||
it('c.notFound()', async () => {
|
||||
const res = c.notFound()
|
||||
expect(res).instanceOf(Response)
|
||||
|
@ -265,7 +265,7 @@ export class Context<
|
||||
* ```
|
||||
*/
|
||||
env: E['Bindings'] = {}
|
||||
#var: E['Variables'] | undefined
|
||||
#var: Map<unknown, unknown> | undefined
|
||||
finalized: boolean = false
|
||||
/**
|
||||
* `.error` can get the error object from the middleware if the Handler throws an error.
|
||||
@ -521,9 +521,9 @@ export class Context<
|
||||
* ```
|
||||
```
|
||||
*/
|
||||
set: Set<E> = (key: string, value: unknown) => {
|
||||
this.#var ??= {}
|
||||
this.#var[key as string] = value
|
||||
set: Set<E> = (key: unknown, value: unknown) => {
|
||||
this.#var ??= new Map()
|
||||
this.#var.set(key, value)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -539,8 +539,8 @@ export class Context<
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
get: Get<E> = (key: string) => {
|
||||
return this.#var ? this.#var[key] : undefined
|
||||
get: Get<E> = (key: unknown) => {
|
||||
return this.#var ? this.#var.get(key) : undefined
|
||||
}
|
||||
|
||||
/**
|
||||
@ -558,7 +558,11 @@ export class Context<
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
ContextVariableMap & (IsAny<E['Variables']> extends true ? Record<string, any> : E['Variables'])
|
||||
> {
|
||||
return { ...this.#var } as never
|
||||
if (!this.#var) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return {} as any
|
||||
}
|
||||
return Object.fromEntries(this.#var)
|
||||
}
|
||||
|
||||
newResponse: NewResponse = (
|
||||
|
@ -3585,3 +3585,36 @@ describe('Compatible with extended Hono classes, such Zod OpenAPI Hono.', () =>
|
||||
expect(res.status).toBe(200)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Generics for Bindings and Variables', () => {
|
||||
interface CloudflareBindings {
|
||||
MY_VARIABLE: string
|
||||
}
|
||||
|
||||
it('Should not throw type errors', () => {
|
||||
// @ts-expect-error Bindings should extend object
|
||||
new Hono<{
|
||||
Bindings: number
|
||||
}>()
|
||||
|
||||
const appWithInterface = new Hono<{
|
||||
Bindings: CloudflareBindings
|
||||
}>()
|
||||
|
||||
appWithInterface.get('/', (c) => {
|
||||
expectTypeOf(c.env.MY_VARIABLE).toMatchTypeOf<string>()
|
||||
return c.text('/')
|
||||
})
|
||||
|
||||
const appWithType = new Hono<{
|
||||
Bindings: {
|
||||
foo: string
|
||||
}
|
||||
}>()
|
||||
|
||||
appWithType.get('/', (c) => {
|
||||
expectTypeOf(c.env.foo).toMatchTypeOf<string>()
|
||||
return c.text('Hello Hono!')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -7,3 +7,36 @@ describe('hono/quick preset', () => {
|
||||
expect(getRouterName(app)).toBe('SmartRouter + LinearRouter')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Generics for Bindings and Variables', () => {
|
||||
interface CloudflareBindings {
|
||||
MY_VARIABLE: string
|
||||
}
|
||||
|
||||
it('Should not throw type errors', () => {
|
||||
// @ts-expect-error Bindings should extend object
|
||||
new Hono<{
|
||||
Bindings: number
|
||||
}>()
|
||||
|
||||
const appWithInterface = new Hono<{
|
||||
Bindings: CloudflareBindings
|
||||
}>()
|
||||
|
||||
appWithInterface.get('/', (c) => {
|
||||
expectTypeOf(c.env.MY_VARIABLE).toMatchTypeOf<string>()
|
||||
return c.text('/')
|
||||
})
|
||||
|
||||
const appWithType = new Hono<{
|
||||
Bindings: {
|
||||
foo: string
|
||||
}
|
||||
}>()
|
||||
|
||||
appWithType.get('/', (c) => {
|
||||
expectTypeOf(c.env.foo).toMatchTypeOf<string>()
|
||||
return c.text('Hello Hono!')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -7,3 +7,36 @@ describe('hono/tiny preset', () => {
|
||||
expect(getRouterName(app)).toBe('PatternRouter')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Generics for Bindings and Variables', () => {
|
||||
interface CloudflareBindings {
|
||||
MY_VARIABLE: string
|
||||
}
|
||||
|
||||
it('Should not throw type errors', () => {
|
||||
// @ts-expect-error Bindings should extend object
|
||||
new Hono<{
|
||||
Bindings: number
|
||||
}>()
|
||||
|
||||
const appWithInterface = new Hono<{
|
||||
Bindings: CloudflareBindings
|
||||
}>()
|
||||
|
||||
appWithInterface.get('/', (c) => {
|
||||
expectTypeOf(c.env.MY_VARIABLE).toMatchTypeOf<string>()
|
||||
return c.text('/')
|
||||
})
|
||||
|
||||
const appWithType = new Hono<{
|
||||
Bindings: {
|
||||
foo: string
|
||||
}
|
||||
}>()
|
||||
|
||||
appWithType.get('/', (c) => {
|
||||
expectTypeOf(c.env.foo).toMatchTypeOf<string>()
|
||||
return c.text('Hello Hono!')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -24,8 +24,8 @@ import type {
|
||||
////// //////
|
||||
////////////////////////////////////////
|
||||
|
||||
export type Bindings = Record<string, unknown>
|
||||
export type Variables = Record<string, unknown>
|
||||
export type Bindings = object
|
||||
export type Variables = object
|
||||
|
||||
export type BlankEnv = {}
|
||||
export type Env = {
|
||||
|
Loading…
Reference in New Issue
Block a user