microsoft / microsoft/TypeScript

optional and readonly Filter Modifier for keyof

オープン
#35,103 コメント 6 件 リアクション 9 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

Awaiting More Feedback Suggestion
主要言語
Go
スター
111k
フォーク
14.4k
平均マージ
1日 19時間
マージ済み PR(30日)
117

説明

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.

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

この issue では、オプショナル、必須、readonly、編集可能なプロパティをフィルタリングするための新しい keyof 修飾子構文を提案していますが、リポジトリのファイル、テスト、エントリポイントは指定されていません。まず既存の keyof と mapped-type の動作を確認してください。完了には、合意された構文とセマンティクス、実装、および提案された組み合わせをカバーするテストが必要です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
typescript
領域
compilers
issue の種類
機能追加
難易度
5/5
見積もり時間
1週間以上
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
25/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。