-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Filter object properties by type #38646
Comments
@weswigham thoughts? |
you could do this to make it compile: type FilteredKeys<T, U> = keyof { [P in keyof T]: T[P] extends U ? P : never }; But this still has other problem sometimes, see: |
In 4.1 (beta) you can do something like:
|
Key remapping is a very nice and useful feature. |
In 4.1, as @shauns mentioned, you can filter out object keys which don't fit the type you want. However, unfortunately, it still can't give you a list of keys which comply with the desired type by the conventional type SelectKeysByValueType<T, U> = {
[K in keyof T as T[K] extends U ? K : never]: T[K]
}[keyof T] // <~ Type 'keyof T' cannot be used to index type See also #40833 |
Any updates on this issue? I have a similar issue here: |
As a workaround, I think this could work: type OriginalType = {
str: string;
num: number;
}
type Values<T> = T[keyof T];
type PickKeys<T, U> = Values<{
[K in keyof T]: T[K] extends U ? K : never;
}>;
type NumberKeys = PickKeys<OriginalType, number>;
type NumberType = Pick<OriginalType, NumberKeys>;
const ok: NumberType = { num: 1 }; // ok
const err: NumberType = { num: 1, str: "" }; // error With the original example rewritten: type FooMap<T> = {
[key in PickKeys<T, number>]: T[key]
}
const ok1: FooMap<OriginalType> = { num: 1 }; // ok
const err2: FooMap<OriginalType> = { num: 1, str: "" }; // error |
I have a workaround, just infer type before mapping it. type FooMap<T> = {
[key in FilteredKeys<T, number>]: FooItem<T[key]>
} to this: type FooMap<T> = T extends infer TT
? {
[key in FilteredKeys<T, number>]: FooItem<T[key]>
}
: never |
@aspic-fish YOU ARE A GENIUS !!!! Thank you so much!!! |
Here's a solution we found to work for us (in this case omitting as opposed to picking), including a recursive option: type OmitKeysByValueType<T, U> = { [P in keyof T]: T[P] extends U ? never : P }[keyof T]
type OmitByValueType<T, V> = T extends infer _
? {
[key in OmitKeysByValueType<T, V>]: T[key]
}
: never
type OmitByValueTypeRecursive<T, V> = T extends object
? T extends infer _
? {
[key in OmitKeysByValueType<T, V>]: OmitByValueTypeRecursive<T[key], V>
}
: never
: T Usage: interface A {
someFunctionIDoNotWant: () => void // <- get rid of this
somePropIDoWant: number
}
interface B {
prop: string
prop2: A
}
type AMinusFunctions = OmitByValueType<A, Function>
// -> { somePropIDoWant: true }
type BMinusFunctionsRecursively = OmitByValueTypeRecursive<B, Function>
// -> { prop: string; prop2: { somePropIDoWant: true } } cc @Orzelius |
A few observations:
The real missing feature is #48992 to handle this in a more analyzable form, so I think we can treat this as a duplicate of that one |
This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
TypeScript Version: 3.9.2
Search Terms:
mapped type filter object properties never
Expected behavior:
The type
type FilteredKeys<T, U> = { [P in keyof T]: T[P] extends U ? P : never }[keyof T];
that allows to extract object properties by type should work everywhere.
Actual behavior:
type FilteredKeys<T, U> = { [P in keyof T]: T[P] extends U ? P : never }[keyof T];
only works externally of the declaring type
Related Issues:
#23199
Code
Output
Compiler Options
Playground Link: Provided
The text was updated successfully, but these errors were encountered: