Challenge
In the process of creating a mapped type that excludes properties of type Function
, we encountered an issue. Our current method not only eliminates functions but also strips away the optional decorator (?
) from the mapped properties.
Scenario
For a clear understanding, you can view a simplified example that highlights this behavior - NoOpMap1
works as intended, while NoOpMap2
showcases the problematic behavior.
type NoOpMap1<T> = { // Successful. Retains the ?
[K in keyof T]: T[K];
};
type Keys<T> = {
[K in keyof T]: K;
}[keyof T];
type NoOpMap2<T> = { // Issue. Removes the ?
[K in Keys<T>]: T[K];
};
Demonstration
type SomeType = {
foo?: string,
}
// type SomeTypeNoOpMap1 = { foo?: string; }
type SomeTypeNoOpMap1 = NoOpMap1<SomeType>;
// type SomeTypeNoOpMap2 = { foo: string; }
type SomeTypeNoOpMap2 = NoOpMap2<SomeType>;
NoOpMap1
operates correctly by retaining the ?
decorator on the foo
property. In contrast, NoOpMap2
removes it unexpectedly.
Inquiry
We are puzzled about why NoOpMap2
is eliminating the ?
decorator. Is there a way to achieve similar results without removing it?
Real-life Example
Below is the comprehensive type structure that we aim to establish:
type DataPropertyNames<T> = {
[K in keyof T]: T[K] extends Function ? never : K;
}[keyof T];
type DataPropertiesOnly<T> = {
[K in DataPropertyNames<T>]
: T[K] extends (string | number | boolean) ? T[K]
: T[K] extends (infer A)[] ? DataPropertiesOnly<A>[]
: DataPropertiesOnly<T[K]>;
};
This defined type plays a crucial role in filtering out function properties while ensuring that the optional ?
decorators remain intact on other properties.