TypeScript Version: 2.2.1 / nightly (2.2.0-dev.201xxxxx)
Code
// A *self-contained* demonstration of the problem follows...
interface AnInterface {
stringProperty: string;
numberProperty: number;
objectProperty: object;
functionProperty1: () => number;
functionProperty2: Function;
functionProperty3(): number;
}
type PickByType<O extends object, T extends any> = {
// suggestion here: we should be able to filter object property somehow.
[K in keyof O && typeof O[K] is T]: O[K];
};
type StringOnly = PickByType<AnInterface, string>; // { stringProperty: string; }
type NumberOnly = PickByType<AnInterface, number>; // { numberProperty: number; }
type ObjectOnly = PickByType<AnInterface, object>; // { objectProperty: object; }
type WithoutFunction = StringOnly & NumberOnly & ObjectOnly; // { stringProperty: string; numberProperty: number; objectProperty: object; }
Expected behavior:
In this scenario, we can pick object's properties by their type.
It will be useful when extracting properties from class type.
Actual behavior:
I couldn't find the way to achieve this scenario.
And also, complex index signature like K in keyof O && typeof O[K] is T is not supported yet.
looks like a duplicate of https://github.com/Microsoft/TypeScript/issues/12424
@mhegazy Sorry for bothering you, I didn't find out a meet solution from #12424
I tried this:
type OmitString<T> = {
[P in keyof T]: T[P] extends string ? never : T[P];
};
type T = OmitString<{ foo: string, bar: number }>;
// T is expanded as:
type T = { foo: never; bar: number; }
We lost the 'in' operator type guard in this way. I expected T is:
type T = { bar: number; }
You want to filter the keys:
type NoneStringKeys<T> = {
[P in keyof T]: T[P] extends string ? never :P;
}[keyof T];
type OmitString<T> = Pick<T, Exclude<keyof T, NoneStringKeys<T>>>;
@mhegazy Thx very much! I learned from you.
Most helpful comment
You want to filter the keys: