Repository navigation
Description
Suggestion
π Search Terms
keyof property keysOfType
β Viability Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This feature would agree with the rest of TypeScript's Design Goals.
β Suggestion
We frequently get people writing definitions to produce the keys K of an object type O where O[K] extends T. Let's call this operation KeysOfType<O, T>. Varying userland definitions include
type ObjectKey<O, T> = {[K in keyof O]: O[K] extends T ? K : never}[keyof O & string]
// TODO: Link more definitionsThese userland definitions work in concrete cases, but can't be used to write generic functions:
type ObjectKey<O, T> = {[K in keyof O]: O[K] extends T ? K : never}[keyof O & string];
function getString<O extends object, K extends ObjectKey<O, string>>(obj: O, key: K): string {
// Can't assign ObjectKey<O, K> to 'string', but this is sound by construction
return obj[key];
}
// Demo
interface MyInterface {
someString: string;
someNumber: number;
}
declare const mi: MyInterface;
getString(mi, "someString"); // OK
getString(mi, "someNumber"); // ErrorWe could add a new type operator or intrinsic alias KeysOfType<T, P> that returns all keyof T K such that T[K] extends P. When this type indexes a generic object of type T, we can then know that T[KeysOfType<T, P>] is assignable to P. In non-generic positions, this can be immediately resolved the same way as the userland definition.
type KeysOfType<O, P> = intrinsic;
// Hypothetical
function getString<O extends object>(obj: O, key: KeysOfType<O, string>): string {
// OK, O[KeysOfType<O, string>] is known to be assignable to
// string because O is a subtype of O and string is assignable to string
return obj[key];
}
// getString works the same from the outside as the userland versionπ Motivating Example
See getString above
π» Use Cases
This is a frequent complaint; need link more inbound issues here
Activity
jcalz commentedon May 6, 2022
related: #30728
RyanCavanaugh commentedon May 6, 2022
Collecting more
#42795
#40654
#39972
#32550
somebody1234 commentedon May 7, 2022
Solution (to codeblock 2) - Playground
jcalz commentedon Apr 19, 2023
Note to self for future ease of searching: I usually call
KeysOfType<O, T>by the nameKeysMatching<T, V>RobertAKARobin commentedon Dec 28, 2023
Sure would be nice to see this implemented! The
KeysMatchingapproach doesn't work when used on the base of a derived class, e.g.:somebody1234 commentedon Dec 28, 2023
Robin (Robert) Thomas (@RobertAKARobin) actually that doesn't even work on the base class.
This does though:
Playground Link
Howard-Lam-UnitedVanning commentedon Apr 19, 2024
Another issue that maybe related to this
In the following, in usetest2, Test2['e'] has the type never even though it should always be number. Or maybe the engine found out a case I never could think of.
EDIT: I have 2 implementations of BooleanKey here they both lead to the same results...
jesseditson commentedon Nov 6, 2024
I'm having trouble trying to get the following to produce the correct type - is this the same issue as this discussion?
Playground
mwaibel-go commentedon Nov 2, 2026
FYI: This feature just landed in 'type-fest': Issue, Implementation