Skip to content

Commit

Permalink
fix(types): add number, symbol as safe key for OmitKeyof for st…
Browse files Browse the repository at this point in the history
…rictness `safely` (#7164)

* types(query-core): add number, symbol as safe key for OmitKeyof  for safely

* test(query-core): add type test case for number key, symbol key

---------

Co-authored-by: Dominik Dorfmeister <office@dorfmeister.cc>
  • Loading branch information
manudeli and TkDodo authored May 6, 2024
1 parent 2c0dc08 commit 753fbac
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 2 deletions.
118 changes: 117 additions & 1 deletion packages/query-core/src/__tests__/OmitKeyof.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { describe, expectTypeOf, it } from 'vitest'
import type { OmitKeyof } from '..'

describe('OmitKeyof', () => {
it("'s type check", () => {
it("'s string key type check", () => {
type A = {
x: string
y: number
Expand Down Expand Up @@ -56,4 +56,120 @@ describe('OmitKeyof', () => {
>
>().toEqualTypeOf<ExpectedType>
})

it("'s number key type check", () => {
type A = {
[1]: string
[2]: number
}

type ExpectedType = {
[1]: string
}

// Bad point
// 1. original Omit can use 3 as type parameter with no type error
// 2. original Omit have no auto complete for 2nd type parameter
expectTypeOf<Omit<A, 3 | 2>>().toEqualTypeOf<ExpectedType>()

// Solution

// 1. strictly
expectTypeOf<
OmitKeyof<
A,
// OmitKeyof can't use 3 as type parameter with type error because A don't have key 3
// @ts-expect-error Type does not satisfy the constraint keyof A
3 | 2
>
>().toEqualTypeOf<ExpectedType>
expectTypeOf<
OmitKeyof<
A,
// OmitKeyof can't use 3 as type parameter with type error because A don't have key 3
// @ts-expect-error Type does not satisfy the constraint keyof A
3 | 2,
'strictly'
>
>().toEqualTypeOf<ExpectedType>

// 2. safely
expectTypeOf<
OmitKeyof<
A,
// OmitKeyof can't use 3 as type parameter type error with strictly parameter or default parameter
// @ts-expect-error Type does not satisfy the constraint keyof A
3 | 2
>
>().toEqualTypeOf<ExpectedType>
expectTypeOf<
OmitKeyof<
A,
// With 'safely', OmitKeyof can use 3 as type parameter like original Omit but This support autocomplete too yet for DX.
3 | 2,
'safely'
>
>().toEqualTypeOf<ExpectedType>
})

it("'s symbol key type check", () => {
const symbol1 = Symbol()
const symbol2 = Symbol()
const symbol3 = Symbol()

type A = {
[symbol1]: string
[symbol2]: number
}

type ExpectedType = {
[symbol1]: string
}

// Bad point
// 1. original Omit can use symbol3 as type parameter with no type error
// 2. original Omit have no auto complete for 2nd type parameter
expectTypeOf<
Omit<A, typeof symbol3 | typeof symbol2>
>().toEqualTypeOf<ExpectedType>()

// Solution

// 1. strictly
expectTypeOf<
OmitKeyof<
A,
// OmitKeyof can't use symbol3 as type parameter with type error because A don't have key symbol3
// @ts-expect-error Type does not satisfy the constraint keyof A
typeof symbol3 | typeof symbol2
>
>().toEqualTypeOf<ExpectedType>
expectTypeOf<
OmitKeyof<
A,
// OmitKeyof can't use symbol3 as type parameter with type error because A don't have key symbol3
// @ts-expect-error Type does not satisfy the constraint keyof A
typeof symbol3 | typeof symbol2,
'strictly'
>
>().toEqualTypeOf<ExpectedType>

// 2. safely
expectTypeOf<
OmitKeyof<
A,
// OmitKeyof can't use symbol3 as type parameter type error with strictly parameter or default parameter
// @ts-expect-error Type does not satisfy the constraint keyof A
typeof symbol3 | typeof symbol2
>
>().toEqualTypeOf<ExpectedType>
expectTypeOf<
OmitKeyof<
A,
// With 'safely', OmitKeyof can use symbol3 as type parameter like original Omit but This support autocomplete too yet for DX.
typeof symbol3 | typeof symbol2,
'safely'
>
>().toEqualTypeOf<ExpectedType>
})
})
6 changes: 5 additions & 1 deletion packages/query-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import type { MutationCache } from './mutationCache'
export type OmitKeyof<
TObject,
TKey extends TStrictly extends 'safely'
? keyof TObject | (string & Record<never, never>)
?
| keyof TObject
| (string & Record<never, never>)
| (number & Record<never, never>)
| (symbol & Record<never, never>)
: keyof TObject,
TStrictly extends 'strictly' | 'safely' = 'strictly',
> = Omit<TObject, TKey>
Expand Down

0 comments on commit 753fbac

Please sign in to comment.