Description
Search Terms
- keyof modifiers
- only optional keys
- only readonly keys
- pick optional properties
- pick required properties
- pick readonly properties
Suggestion
Adding Support for modifiers to keyof could be very helpful. I'm picturing something like this
type Koptional = keyof? T;
type Kreadonly = readonly keyof T;
// Negations
type Krequired = keyof!? T;
type Keditable = !readonly keyof T;
// Combinations
type KrequiredReadonly = readonly keyof!? T;
The modifiers would act as "filters", only selecting the keys fitting the given modifiers.
As @jcalz pointed out, it might make more sense to use the existing +
and -
operators instead of the !
.
Use Cases
This could be really useful for selecting properties of types based on them being optional
/ readonly
. A possible use case for this would be the React defaultProps
object (see example).
Of course this could negatively affect readability as especially Mapped Types can get fairly long
type PickEditableRequired<T> = {
[P in !readonly keyof!? T]: T[P];
};
but I think it's still in the realms of comprehensibility.
Examples
type PickOptional<T> = {
[P in keyof? T]-?: T[P];
};
type DrinkProps = {
whoGetsUpAndMakesIt: string,
type?: "water" | "coffee" | "coke" | "more coffee",
vessel?: "cup" | "glass" | "HUGE cup",
amount?: number
};
class Drink extends React.Component<Required<DrinkProps>> {
public static defaultProps: PickOptional<DrinkProps> = {
type: "water",
vessel: "glass",
amount: 250
}
render() {
return <p>
{this.props.whoGetsUpAndMakesIt} gets up and pours
{this.props.amount}ml of {this.props.type} into a
{this.props.vessel}.
</p>
}
}
Especially with many optional props the current method of
public static defaultProps: Pick<DrinkProps, "type" | "vessel" | "amount"> = { ... };
can get fairly tedious, especially as you have to add new optional props at 3 places (the type definition, the Pick
UtilityType and in the defaultProps
). The method using PickOptional and the ?
-keyof
-modifier reduces it to 2, and immediately notifies you if you declared a parameter optional, but haven't defined it in defaultProps
.
This would also work without React in terms of default values:
type Order = {
item: string,
amount?: number,
shipping?: "standard" | "express"
}
const defaultOrder: PickOptional<Order> = {
amount: 1,
shipping: "standard"
}
function placeOrder(order: Order): void {
let data: Required<Order> = {...defaultOrder, ...order};
console.log(`You ordered ${data.amount} ${data.item} with ${data.shipping} shipping.`);
}
I'm sure there are more (and better) use cases for this feature I can't think of right now...
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, etc.)
- This feature would agree with the rest of TypeScript's Design Goals.