Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ConditionalKeys<Base, Condition> fails when used on Arrays #119

Closed
KilianKilmister opened this issue Aug 15, 2020 · 2 comments
Closed

ConditionalKeys<Base, Condition> fails when used on Arrays #119

KilianKilmister opened this issue Aug 15, 2020 · 2 comments
Labels
bug Something isn't working

Comments

@KilianKilmister
Copy link

KilianKilmister commented Aug 15, 2020

There is a bug in Typescript related to keyof Array that affects ConditionalKeys<Base, Condition> and the Types using it. (reporting the bug itself to typescript, aswell)
It can be fixed adHoc without affecting any non.bugged existing uses

case:

Playground Link

type Arr = readonly [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

type WhoopMyArray_Faulty<Base extends ArrayLike<any>, Condition> = {  
		[Key in keyof Base]:
			Base[Key] extends Condition
				? 'Whoop it'
				: Base[Key] extends Base[number] ?  Base[Key] : never
	}

// action is performed on array elements but includes all values of Array.prototype
type WhoopedArrayKeys = WhoopMyArray_Faulty<Arr, 7 | 5 | 2>[keyof Arr]

So using ConditionalKeys<Base, Condition>

Playground Link

import { ConditionalKeys } from 'type-fest'

type WhoopedArray = readonly [0, 1, 'Whoop it', 3, 'Whoop it', 5, 'Whoop it', 7, 8, 9]
type WhoopedArrayKeys = ConditionalKeys<WhoopedArray, 'Whoop it'>

results in "2" | "4" | "6" and all Array.prototype-values

this can be fixed by adding a temporary dummy key to the UtilityType:

Playground Link

type WhoopedArray = [0, 1, 'Whoop it', 3, 'Whoop it', 5, 'Whoop it', 7, 8, 9]

export type ConditionalKeys<Base, Condition> = NonNullable< // TODO: report bug in ts as type-fest
	// Wrap in `NonNullable` to strip away the `undefined` type from the produced union.
	{
		// Map through all the keys of the given base type. NOTE: dummy-prop is needed for Arrays
		[Key in keyof Base | '__im-a-dummy-prop__']:
			// Pick only keys with types extending the given `Condition` type.
			Base[Exclude<Key, '__im-a-dummy-prop__'>] extends Condition
				// Retain this key since the condition passes.
				? Key
				// Discard this key since the condition fails.
				: never
	// Convert the produced object into a union type of the keys which passed the conditional test.
	}[keyof Base]
>;

type WhoopedArrayKeys = ConditionalKeys<WhoopedArray, 'Whoop it'>
// -> '2' | '4'  |  '6'

Took me ages to find out why my stuff isn't working

Upvote & Fund

  • We're using Polar.sh so you can upvote and help fund this issue.
  • The funding will be given to active contributors.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar
@0f-0b
Copy link

0f-0b commented Jun 1, 2023

This fix does not involve an arbitrary dummy key.

export type ConditionalKeys<Base, Condition> = {
	// Map through all the keys of the given base type.
	[Key in Exclude<keyof Base, never>]:
	// Pick only keys with types extending the given `Condition` type.
	Base[Key] extends Condition
	// Retain this key since the condition passes.
		? Key
	// Discard this key since the condition fails.
		: never;

	// Convert the produced object into a union type of the keys which passed the conditional test.
}[keyof Base];

@fregante fregante added the bug Something isn't working label Aug 13, 2024
@fregante fregante changed the title Bug: ConditionalKeys<Base, Condition> fails when used on Arrays ConditionalKeys<Base, Condition> fails when used on Arrays Aug 13, 2024
@fregante
Copy link
Collaborator

As pointed out in the TS repo issue, keyof shouldn't be used on arrays, and I don't understand why you'd want to use ConditionalKeys on an array either as arrays don't have "keys" but "indexes"

@fregante fregante closed this as not planned Won't fix, can't repro, duplicate, stale Aug 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants